perm filename SAIL.DCS[S,DOC]1 blob
sn#011063 filedate 1972-06-11 generic text, type T, neo UTF8
00100 SAILON NO. 57.2 SAIL 1
00200
00300 TABLE OF CONTENTS
00400
00500
00600
00700
00800 CONTENT PARAGRAPH
00900
01000
01100
01200 SECTION 1--INTRODUCTION
01300
01400 SECTION 2--PROGRAMS, BLOCKS, STATEMENTS
01500 SYNTAX 2- 1
01600 EXAMPLES 2- 2
01700 SEMANTICS 2- 3
01800 Declarations 2- 3
01900 Statements 2- 6
02000 Block Names 2- 9
02100 Entry Specifications 2-11
02200
02300 SECTION 3--DECLARATIONS
02400 SYNTAX 3- 1
02500 RESTRICTIONS 3- 2
02600 EXAMPLES 3- 6
02700 SEMANTICS 3- 8
02800 Scope of declarations 3- 8
02900 Type Declarations 3-11
03000 Numeric Declarations 3-13
03100 String Declarations 3-15
03200 Item Declarations 3-18
03300 Items 3-19
03400 Item Genesis 3-20
03500 Datums 3-21
03600 Itemvar Declarations 3-22
03700 Set Declarations 3-24
03800 Array Declarations 3-25
03900 Preload Specifications 3-33
04000 Procedure Declarations 3-38
04100 Formal Parameters 3-39
04200 Forward Procedure Declarations 3-42
04300 Recursive Procedures 3-44
04400 External Procedures 3-47
04500 Parametric Procedures 3-51
04600 Defaults in Procedure Declarations 3-53
04700 Restrictions on Procedure Declarations 3-54
04800 Synonyms 3-55
04900 Define Specification 3-56
05000 Requirements 3-57
05100
00100 SAILON NO. 57.2 SAIL 2
00200
00300 SECTION 4--ASSIGNMENT STATEMENTS
00400 SYNTAX 4- 1
00500 RESTRICTION 4- 2
00600 SEMANTICS 4- 3
00700 Datum Assignments 4- 7
00800 Swap Assignment 4- 8
00900 Byte statements 4-10
01000
01100 SECTION 5--EXECUTION CONTROL STATEMENTS
01200 SYNTAX 5- 1
01300 SEMANTICS 5- 2
01400 Conditional Statements 5- 2
01500 If Statement 5- 4
01600 If ... Else Statement 5- 5
01700 Ambiguity in Conditional Statements 5- 6
01800 Go To Statements 5- 8
01900 For Statements 5-11
02000 While Statement 5-16
02100 Do Statement 5-17
02200 Case Statements 5-18
02300 Return Statement 5-20
02400 Done Statement 5-24
02500 Next Statement 5-26
02600 Continue Statement 5-30
02700
02800 SECTION 6--PROCEDURE STATEMENTS
02900 SYNTAX 6- 1
03000 SEMANTICS 6- 2
03100 Actual Parameters 6- 4
03200 Call by Value 6- 5
03300 Call by Reference 6- 6
03400 Procedures as Actual Parameters 6-10
03500 Fortran Procedures 6-12
03600 Implementation Details 6-15
03700 Examples: 6-16
03800
03900 SECTION 7--LEAP STATEMENTS
04000 SYNTAX 7- 1
04100 SEMANTICS 7- 2
04200 LEAP Introduction 7- 2
04300 General Restrictions 7- 7
04400 Construction - Retrieval Distinction 7- 8
04500 PUT and REMOVE 7- 9
04600 DELETE 7-10
04700 MAKE 7-11
04800 ERASE 7-13
04900 FOREACH Statement 7-15
05000 Restrictions and Caveats 7-22
05100
00100 SAILON NO. 57.2 SAIL 3
00200
00300 SECTION 8--ASSEMBLY LANGUAGE STATEMENTS
00400 SYNTAX 8- 1
00500 SEMANTICS 8- 2
00600 Declarations in Code Blocks 8- 3
00700 Meaning of Instruction Operands 8- 4
00800 Distinctions Between START_CODE and QUICK_CODE 8- 7
00900 Warning Concerning Default Radix 8- 8
01000
01100 SECTION 9--ALGEBRAIC EXPRESSIONS
01200 SYNTAX 9- 1
01300 SEMANTICS 9- 2
01400 Conditional Expressions 9- 2
01500 Example 9- 3
01600 Assignment Expressions 9- 4
01700 Example 9- 5
01800 Case Expressions 9- 6
01900 Example 9- 8
02000 Simple Expressions 9- 9
02100 The Boolean Expression Anomaly 9-10
02200 Precedence of Algebraic Operators 9-13
02300 Expression Evaluation Rules 9-14
02400 Algebraic Expressions 9-15
02500 Disjunctive Expressions 9-18
02600 Relational Expressions 9-19
02700 Arithmetic Type Conversions 9-21
02800 String-Arithmetic Conversions 9-27
02900 Bounded Expressions 9-29
03000 Adding Expressions 9-30
03100 Terms 9-33
03200 Concatenation Operator 9-38
03300 Factors 9-39
03400 Primaries 9-40
03500 Variables and Constants 9-41
03600 Substrings 9-42
03700 Special Length Operator (∞) 9-45
03800 Function Designators 9-47
03900 Length 9-50
04000 Lop 9-51
04100 Cvn 9-52
04200 Lnot 9-53
04300 Abs 9-54
04400 Unary Minus 9-55
04500 Boolean Primaries 9-56
04600 ISTRIPLE 9-57
04700 LDB and ILDB 9-58
04800
04900 SECTION 10--SET AND ASSOCIATIVE EXPRESSIONS
05000 SYNTAX 10- 1
05100 SEMANTICS 10- 2
00100 SAILON NO. 57.2 SAIL 4
00200
00300 Set Expressions 10- 2
00400 Set Primaries 10- 3
00500 Item Constructs 10- 4
00600 Item Selectors 10- 5
00700 NEW Items 10- 6
00800 NEW_ITEM Declaration 10- 6
00900 ANY Construct 10- 7
01000 CVI 10- 8
01100 LEAP Booleans 10- 9
01200
01300 SECTION 11--BASIC CONSTRUCTS
01400 SYNTAX 11- 1
01500 SEMANTICS 11- 2
01600 Variables 11- 2
01700 Datums 11- 6
01800 Identifiers 11- 7
01900 Sail Reserved Words 11-10
02000 Sail Predeclared Identifiers 11-12
02100 Arithmetic Constants 11-15
02200 String Constants 11-19
02300 Examples 11-22
02400 Comments 11-24
02500
02600 SECTION 12--EXECUTION TIME ROUTINES
02700 GENERAL 12- 1
02800 Scope 12- 1
02900 Notational Conventions 12- 3
03000 Example 12- 5
03100 I/O ROUTINES 12- 6
03200 Open 12- 6
03300 Close, Closin, Closo 12-10
03400 Getchan 12-12
03500 Release 12-14
03600 Lookup, Enter 12-17
03700 Rename 12-21
03800 Breakset 12-22
03900 Setbreak 12-35
04000 Stdbrk 12-37
04100 Input 12-40
04200 Scan 12-43
04300 Out 12-45
04400 Linout 12-46
04500 Wordin 12-48
04600 Arryin 12-50
04700 Wordout 12-53
04800 Arryout 12-55
04900 Mtape 12-57
05000 Useti, Useto 12-59
05100 Realin, Intin 12-61
00100 SAILON NO. 57.2 SAIL 5
00200
00300 Realscan, Intscan 12-66
00400 Teletype I/O Functions 12-68
00500 Pseudo-teletype functions (Stanford only) 12-70
00600 STRING MANIPULATION ROUTINES 12-72
00700 Equ 12-73
00800 TYPE CONVERSION ROUTINES 12-75
00900 Setformat 12-75
01000 Getformat 12-78
01100 Cvs 12-80
01200 Cvos 12-82
01300 Cvis 12-84
01400 Cvsi 12-86
01500 New_Pname 12-88
01600 Del_Pname 12-90
01700 Cve, Cvf, Cvg 12-92
01800 Cvstr 12-97
01900 Cvxstr 12-99
02000 Cvd 12-101
02100 Cvo 12-103
02200 Cvasc 12-105
02300 Cvsix 12-107
02400 Cvfil 12-109
02500 Arrinfo 12-110
02600 Arrblt 12-112
02700 Arrtran 12-114
02800 LIBERATION-FROM-SAIL ROUTINES 12-116
02900 Code 12-116
03000 Call 12-118
03100 Usercon 12-120
03200 Usererr 12-124
03300 Point 12-126
03400
03500 SECTION 13--USE OF DEFINE
03600 Defining Macros 13- 1
03700 String Constants in Macro Bodies 13- 4
03800 Using Macros 13- 5
03900 Macro Parameters 13- 6
04000 Example 13- 8
04100 Actual Parameter Expansion 13- 9
04200 Examples 13-11
04300
04400 SECTION 14--COMPILER OPERATION
04500 COMMAND FORMAT 14- 1
04600 Semantics 14- 2
04700 Rpg Mode 14-12
04800 Switches 14-13
04900 Debugging modes 14-14
05000 ERROR MESSAGES 14-19
05100 STORAGE ALLOCATION 14-22
00100 SAILON NO. 57.2 SAIL 6
00200
00300
00400 SECTION 15--PROGRAM OPERATION
00500 LOADING AND STARTING SAIL PROGRAMS 15- 1
00600 Loading 15- 1
00700 Starting the Program -- Normal Operation 15- 2
00800 Starting the Program in "RPG" Mode 15- 3
00900 Starting the Program with Allocation Modifications 15- 4
01000 ERROR MESSAGES 15- 5
01100 DEBUGGING 15- 9
01200 Symbols 15-10
01300 Blocks 15-13
01400 Sail-Generated Symbols 15-14
01500 Warnings 15-15
01600 Long Names 15-16
01700
01800 SECTION 16--PROGRAM STRUCTURE
01900 THE SAIL CORE IMAGE (REQUIRED) 16- 1
02000 Main Program 16- 2
02100 Storage Allocation, Basic Utilities 16- 4
02200 Other Execution-Time Routines 16- 6
02300 OPTIONAL ADDITIONS 16- 7
02400 Separately Compiled Procedures 16- 7
02500 Fortran Procedures 16-11
02600 Assembly Language Procedures 16-12
02700 Others 16-13
02800
02900 SECTION 17--IMPLEMENTATION INFORMATION
03000 STORAGE LAYOUT 17- 1
03100 User Table 17- 1
03200 Storage Allocation Routines 17- 5
03300 Corget 17- 6
03400 Correl 17-10
03500 Corinc 17-11
03600 Caninc 17-12
03700 Corbig 17-13
03800 STRINGS 17-15
03900 String Descriptors 17-15
04000 String Operations 17-20
04100 Cat 17-21
04200 Substr 17-22
04300 String to Integer 17-26
04400 Putch 17-27
04500 Lop Details 17-28
04600 String Space 17-29
04700 Parameters Used by String Operations 17-31
04800 String Garbage Collection 17-32
04900 String-Oriented Machine Language Routines 17-33
05000 ARRAY IMPLEMENTATION 17-35
05100 Form 17-35
00100 SAILON NO. 57.2 SAIL 7
00200
00300 Explanation 17-36
00400 Array Allocation 17-37
00500 Dynamic Arrays 17-37
00600 Built-In Arrays 17-40
00700 Array Access Code 17-44
00800 PROCEDURE IMPLEMENTATION 17-48
00900 Procedure Body 17-49
01000 Discussion 17-50
01100 Procedure Calling Sequences 17-51
01200 Discussion 17-52
01300
01400 SECTION 18--APPENDIX -- USEFUL SUMMARIES
01500 ARITHMETIC TYPE-CONVERSION TABLE 18- 1
01600 SAIL RESERVED WORDS 18- 2
01700 SAIL PRE-DECLARED IDENTIFIERS 18- 3
01800 CHARACTER-IDENTIFIER EQUIVALENCES 18- 4
01900 PARAMETERS TO THE OPEN FUNCTION 18- 5
02000 BREAKSET MODES 18- 6
02100 MTAPE COMMANDS 18- 7
02200 COMMAND SWITCHES 18- 8
02300 DEBUGGING MODES 18- 9
02400 VALID RESPONSES TO ERROR MESSAGES 18-10
02500 NON-FATAL ERROR, EXCEPTIONAL CONDITION RETURN CODES 18-11
02600
02700 SECTION 19--BIBLIOGRAPHY
02800
00100 SAILON NO. 57.2 SAIL 1-1
00200
00300 SECTION 1
00400
00500 INTRODUCTION
00600
00700
00800
00900 1-1. SAIL is a high-level programming system for the PDP-10
01000 computer. It includes an extended ALGOL compiler and a companion set
01100 of execution-time routines. A non-standard ALGOL 60 compiler is
01200 extended to provide facilities for describing manipulations of an
01300 associative data structure. This structure contains information
01400 about ITEMS, stored as unordered collections of items (sets) or as
01500 ordered triples of items (associations). The algebraic capabilities
01600 of the language are linked to the associative capabilities by means
01700 of the DATUM operator, which can associate with any ITEM an algebraic
01800 datum.
01900
02000
02100 1-2. Several forerunners (namely the GOGOL compilers developed at
02200 the Stanford Artificial Intelligence Project) have contributed to the
02300 general appearance of the non-associative portions of the SAIL
02400 language. The associative data structure is a slightly reworked
02500 version of the LEAP language, which was designed by J. Feldman and
02600 P. Rovner, and implemented on Lincoln Laboratory's TX-2. This
02700 language is described in some detail in an article entitled "An
02800 Algol-Based Associative Language" in the August, 1969 issue of the
02900 ACM Communications [Feldman&Rovner]. The implementation was modified
03000 to tolerate the non-paging environment of the PDP-10.
03100
03200
03300 1-3. SAIL in a sense has something for everyone. For those who
03400 think in ALGOL, SAIL has ALGOL. For those who want the most from the
03500 PDP-10 and the time-sharing system, SAIL allows flexible linking to
03600 hand-coded machine language programs. For those who have complex
03700 input/output requirements, the language provides complete access to
03800 the I/O facilities of the PDP-10 system. For those who aspire to
03900 speed, SAIL generates fairly good code. The user should, however, be
04000 warned that SAIL falls several man-decades short of the extensive
04100 testing and optimization efforts contained in the histories of most
04200 commercial compilers.
04300
04400
04500
04600 D. Swinehart
04700 R. Sproull
04800 November, 1969
04900 Revised January, 1971
05000
05100
00100 SAILON NO. 57.2 SAIL 2-1
00200
00300 SECTION 2
00400
00500 PROGRAMS, BLOCKS, STATEMENTS
00600
00700
00800
00900 SYNTAX
01000
01100
01200 2-1.
01300
01400
01500 <program> ::= <block>
01600 ::= <entry_specification> <block>
01700
01800 <block> ::= <block_head> ; <compound_tail>
01900
02000 <block_head> ::= BEGIN <declaration>
02100 ::= BEGIN <block_name> <declaration>
02200 ::= <block_head> ; <declaration>
02300
02400 <compound_tail> ::= <statement> END
02500 ::= <statement> END <block_name>
02600 ::= <statement> ; <compound_tail>
02700
02800
02900
03000 <statement> ::= <block>
03100 ::= <compound_statement>
03200 ::= <assignment>
03300 ::= <byte_statement>
03400 ::= <conditional_statement>
03500 ::= <if_statement>
03600 ::= <go_to_statement>
03700 ::= <for_statement>
03800 ::= <while_statement>
03900 ::= <do_statement>
04000 ::= <case_statement>
04100 ::= <return_statement>
04200 ::= <done_statement>
04300 ::= <next_statement>
04400 ::= <continue_statement>
04500 ::= <leap_statement>
04600 ::= <procedure_statement>
04700 ::= <code_block>
04800 ::= <define_specification>
04900 ::= <string_constant> <statement>
05000 ::= <label_identifier> : <statement>
05100 ::= <empty>
00100 SAILON NO. 57.2 SAIL 2-1
00200
00300
00400 <compound_statement> ::= BEGIN <compound_tail>
00500 ::= BEGIN <block_name> <compound_tail>
00600
00700 <block_name> ::= <string_constant>
00800
00900 <entry_specification> ::= ENTRY <id_list>
01000
01100
01200
01300 EXAMPLES
01400
01500
01600 2-2.
01700 Given:
01800 S is a statement,
01900 Sc is a Compound Statement,
02000 D is a Declaration,
02100 B is a Block.
02200
02300 Then:
02400 (Sc) BEGIN S; S; S; ... ; S END
02500 (Sc) BEGIN "SORT" S; S; ... ;S END
02600 (B) BEGIN D; D; D; ... ; S; S; S; ... ; S END
02700 (B) BEGIN "ENTER NEW INFO" D; D; ... ; S; ... ;S END
02800
02900 are syntactically valid SAIL constructs.
03000
03100
03200
03300 SEMANTICS
03400
03500 Declarations
03600
03700
03800 2-3. SAIL programs are organized in the traditional block
03900 structure of ALGOL-60.
04000
04100
04200 2-4. Declarations serve to define the data types and dimensions of
04300 simple and subscripted (array) variables (arithmetic variables,
04400 strings, sets, and items). They are also used to describe procedures
04500 (subroutines) and name program labels. The DEFINE construct (see
04600 DECLARATIONS, 3-1, USE OF DEFINE, 13-0) may also appear in
04700 declarations.
00100 SAILON NO. 57.2 SAIL 2-5
00200
00300
00400
00500 2-5. Any identifier referred to in a program must be described in
00600 some declaration. An identifier may only be referenced by statements
00700 within the scope (see Scope of declarations, 3-8) of its declaration.
00800
00900
01000 Statements
01100
01200
01300 2-6. As in ALGOL, the statement is the fundamental unit of
01400 operation in the SAIL language. Since a statement within a block or
01500 compound statement may itself be a block or compound statement, the
01600 concept of statement must be understood recursively.
01700
01800
01900 2-7. This definition of a block as a statement has virtues other
02000 than its syntactic niceness. In many ways a block behaves as a
02100 single complex statement; most importantly, no transfers (jumps) may
02200 be made to any statement within it except the first (There are now
02300 (unfortunately?) exceptions, see Go To Statements, 5-8). This
02400 assures proper allocation and initialization of the data space for
02500 the block.
02600
02700
02800 2-8. The block representing the program is known as the
02900 "outer block". All blocks internal to this one will be referred to
03000 as "inner blocks".
03100
03200
03300 Block Names
03400
03500
03600 2-9. The block name construct is used to describe the block
03700 structure of a SAIL program to a symbolic debugging routine (see
03800 DEBUGGING, 15-9). The name of the outer block becomes the title of
03900 the binary output file (not necessarily the file name). In addition,
04000 if a block name is used following an END, the compiler compares it
04100 with the block name which followed the corresponding BEGIN. A
04200 mismatch is reported to the user as evidence of a missing (extra)
04300 BEGIN or END somewhere. The block name is also used in conjunction
04400 with the DONE, NEXT, and CONTINUE statements (see Done Statement,
04500 5-24 and following).
04600
04700
04800 2-10. The <string_constant> <statement> construct is equivalent in
04900 action to the <statement> alone; that is, the string constant serves
05000 only as a comment.
00100 SAILON NO. 57.2 SAIL 2-10
00200
00300
00400
00500 Entry Specifications
00600
00700
00800 2-11. See Separately Compiled Procedures, 16-7.
00100 SAILON NO. 57.2 SAIL 3-1
00200
00300 SECTION 3
00400
00500 DECLARATIONS
00600
00700
00800
00900 SYNTAX
01000
01100
01200 3-1.
01300
01400 <id_list> ::= <identifier>
01500 ::= <identifier> , <id_list>
01600
01700
01800
01900 <declaration> ::= <type_declaration>
02000 ::= <array_declaration>
02100 ::= <preload_specification>
02200 ::= <label_declaration>
02300 ::= <procedure_declaration>
02400 ::= <define_specification>
02500 ::= <synonym_declaration>
02600 ::= <requirement>
02700
02800
02900
03000 <type> ::= <algebraic_type>
03100 ::= <leap_type>
03200 ::= <algebraic_type> <leap_type>
03300 ::= <algebraic_type> ARRAY <leap_type>
03400 ::= SET
03500 ::= SET <leap_type>
03600 ::= SET ARRAY <leap_type>
03700 ::= <type_qualifier> <type>
03800
03900 <algebraic_type> ::= REAL
04000 ::= INTEGER
04100 ::= BOOLEAN
04200 ::= STRING
04300
04400 <leap_type> ::= ITEM
04500 ::= ITEMVAR
00100 SAILON NO. 57.2 SAIL 3-1
00200
00300
00400 <type_qualifier> ::= EXTERNAL
00500 ::= INTERNAL
00600 ::= SAFE
00700 ::= FORWARD
00800 ::= RECURSIVE
00900 ::= FORTRAN
01000 ::= OWN
01100 ::= SHORT
01200
01300
01400
01500 <type_declaration> ::= <type> <id_list>
01600
01700
01800
01900 <array_declaration> ::= <type> ARRAY <array_list>
02000
02100 <array_list> ::= <array_segment>
02200 ::= <array_list> , <array_segment>
02300
02400 <array_segment> ::= <id_list> [ <bound_pair_list> ]
02500
02600 <bound_pair_list> ::= <bound_pair>
02700 ::= <bound_pair_list> , <bound_pair>
02800
02900 <bound_pair> ::= <lower_bound> : <upper_bound>
03000
03100 <lower_bound> ::= <algebraic_expression>
03200
03300 <upper_bound> ::= <algebraic_expression>
03400
03500 <preload_specification> ::= PRELOAD_WITH <preload_list>
03600
03700 <preload_list> ::= <preload_element>
03800 ::= <preload_list> , <preload_element>
03900
04000 <preload_element> ::= <expression>
04100 ::= [expression] <expression>
04200
04300
04400
04500 <label_declaration> ::= LABEL <id_list>
04600
04700
00100 SAILON NO. 57.2 SAIL 3-1
00200
00300
00400 <procedure_declaration> ::= PROCEDURE <identifier> <procedure_head>
00500 <procedure_body>
00600 ::= <type> PROCEDURE <identifier>
00700 <procedure_head> <procedure_body>
00800
00900 <procedure_head> ::= <empty>
01000 ::= ( <formal_param_decl> )
01100
01200 <procedure_body> ::= <empty>
01300 ::= ; <statement>
01400
01500 <formal_param_decl> ::= <formal_parameter_list>
01600 ::= <formal_parameter_list> ;
01700 <formal_param_decl>
01800
01900 <formal_parameter_list> ::= <formal_type> <id_list>
02000
02100 <formal_type> ::= <simpler_formal_type>
02200 ::= REFERENCE <simpler_formal_type>
02300 ::= VALUE <simpler_formal_type>
02400
02500 <simpler_formal_type> ::= <type>
02600 ::= <type> ARRAY
02700 ::= <type> PROCEDURE
02800
02900
03000
03100 <define_specification> ::= DEFINE <definition_list>
03200
03300 <definition_list> ::= <definition>
03400 ::= <definition> , <definition_list>
03500
03600 <definition> ::= <define_identifier> = <define_body>
03700
03800 <define_identifier> ::= <identifier>
03900 ::= <identifier> ( <id_list> )
04000
04100 <define_body> ::= <string_constant>
04200
04300 <synonym_declaration> ::= LET <synonym_list>
04400
04500 <synonym_list> ::= <synonym>
04600 ::= <synonym_list> , <synonym>
04700
04800 <synonym> ::= <identifier> = <reserved_word>
04900
05000 <requirement> ::= REQUIRE <require_list>
00100 SAILON NO. 57.2 SAIL 3-1
00200
00300
00400 <require_list> ::= <require_element>
00500 ::= <require_list> , <require_element>
00600
00700 <require_element> ::= <arithmetic_constant> <space_spec>
00800 ::= <string_constant> <file_spec>
00900
01000 <space_spec> ::= STRING_SPACE
01100 ::= SYSTEM_PDL
01200 ::= STRING_PDL
01300 ::= ARRAY_PDL
01400 ::= NEW_ITEMS
01500 ::= PNAMES
01600
01700 <file_spec> ::= LOAD_MODULE
01800 ::= LIBRARY
01900 ::= SOURCE_FILE
02000 ::= SEGMENT_FILE
02100 ::= SEGMENT_NAME
02200
02300
02400
02500 RESTRICTIONS
02600
02700
02800 3-2. For simplicity, the type_qualifiers are listed in only one
02900 syntactic class. Although their uses are always valid when placed
03000 according to the above syntax, most of them only have meaning when
03100 applied to particular subsets of these productions:
03200
03300 SAFE is only meaningful in array declarations
03400 INTERNAL/EXTERNAL have no meaning in formal parameter
03500 declarations
03600 FORWARD, RECURSIVE, and FORTRAN have meaning only in procedure
03700 type specifications.
03800 ITEM ARRAYS and PROCEDURES do not exist (use ITEMVAR).
03900 SHORT has meaning only when applied to INTEGER or REAL
04000 entities.
04100
04200
04300 3-3. For array declarations in the outer block substitute
04400 <constant_expression> for <algebraic_expression> in the productions
04500 for <lower_bound> and <upper_bound>.
04600
04700
04800 3-4. A label must be declared in the innermost block in which the
04900 statement being labeled appears.
00100 SAILON NO. 57.2 SAIL 3-5
00200
00300
00400
00500 3-5. The syntax for procedure declarations requires semantic
00600 embellishment (see Procedure Declarations, 3-38) in order to make
00700 total sense. In particular, a procedure body may be empty only in a
00800 restricted class of declarations.
00900
01000
01100 EXAMPLES
01200
01300
01400 3-6. Let I,J,K,L,X,Y, and P be identifiers, S a statement:
01500
01600 (<type_declaration>) INTEGER I,J,K
01700 EXTERNAL REAL X,Y
01800 ITEM I
01900 SET P
02000 ITEMVAR X
02100 REAL ITEM Y
02200 INTEGER ARRAY ITEM J[X:Y]
02300 INTERNAL STRING K
02400
02500
02600 (<array_declaration>) INTEGER ARRAY X[0:10,0:10]
02700 REAL ARRAY Y[X:P(L)]; Comment illegal
02800 in outer block
02900 STRING ARRAY I[0:IF BIG THEN 30 ELSE 3]
03000 ITEMVAR ARRAY K[0:5,1:L]
03100 REAL ARRAY ITEMVAR ARRAY P[0:15]
03200
03300
03400 (<label_declaration>) LABEL L,X,Y
03500
03600
03700 (<procedure declaration>) PROCEDURE P; S
03800 PROCEDURE P(INTEGER I,J;
03900 REFERENCE REAL X; REAL Y) ; S
04000 INTEGER PROCEDURE P (REAL PROCEDURE L;
04100 STRING I,J; INTEGER ARRAY K); S
04200 EXTERNAL PROCEDURE P(REAL X)
04300 FORWARD INTEGER PROCEDURE X(INTEGER I)
04400 FORTRAN REAL PROCEDURE SIN
04500
04600
04700 (<define_specification>) DEFINE CR="'15", LF="'12",
04800 CRLF = "(CR&LF)",
04900 TTY="1",
05000 TYPE(MSG)="OUT(TTY,MSG&CRLF)"
00100 SAILON NO. 57.2 SAIL 3-7
00200
00300
00400
00500 3-7. Note that these sample declarations are all given without the
00600 semicolons which would normally separate them from the surrounding
00700 declarations and statements. Here is a sample block to bring it all
00800 together (again, let S be any statement, D any declaration, and other
00900 identifiers as above:
01000
01100
01200 BEGIN "SAMPLE BLOCK"
01300 INTEGER I,J,K;
01400 REAL X,Y;
01500 STRING A;
01600 INTEGER PROCEDURE P(REFERENCE REAL X; REAL Y);
01700 BEGIN
01800 D; D; D; ... ;S; ... ; S
01900 END "P";
02000
02100 REAL ARRAY DIPHTHONGS[0:10,1:100];
02200
02300 S; S; S; S
02400 END "SAMPLE BLOCK"
02500
02600
02700
02800 SEMANTICS
02900
03000 Scope of declarations
03100
03200
03300 3-8. Every block automatically introduces a new level of
03400 nomenclature. Any identifier declared in a block's head is said to
03500 be LOCAL to that block. This means that:
03600
03700 a. The entity represented by this identifier inside the block
03800 has no existence outside the block.
03900
04000 b. Any entity represented by the same identifier outside the
04100 block is completely inaccessible (unless it has been passed
04200 as a parameter) inside the block.
04300
04400
04500 3-9. An identifier occurring within an inner block and not
04600 declared within that block will be nonlocal (global) to it; that is,
04700 the identifier will represent the same entity inside the block and in
04800 the block or blocks within which it is nested, up to and including
04900 the level in which the identifier is declared.
00100 SAILON NO. 57.2 SAIL 3-10
00200
00300
00400
00500 3-10. The Scope of an entity is the set of blocks in which the
00600 entity is represented, using the above rules, by its identifier. An
00700 entity may not be referenced by any statement outside its scope.
00800
00900
01000 Type Declarations
01100
01200
01300 3-11. SAIL reserves either one or two 36-bit words for each
01400 identifier appearing in a type declaration (exception -- no space is
01500 reserved for items -- see Item Declarations, 3-18). The use of these
01600 cells falls into two classes -- values and descriptors -- depending
01700 on the type preceding the identifier. If an identifier represents a
01800 REAL or INTEGER (BOOLEAN) variable or an ITEMVAR, its value is stored
01900 directly in the reserved cell. For strings (2 words, see String
02000 Declarations, 3-15) and sets (1 word, see Set Declarations, 3-24)
02100 internal descriptors are placed in the reserved cells which allow the
02200 running program to access these entities. These differences are not
02300 reflected in the SAIL syntax. The user may treat entities of both
02400 kinds as if their values were directly accessible in the reserved
02500 locations. For this reason we will henceforth refer synonymously to
02600 a simple identifier (one declared in a type declaration) and the
02700 simple variable it represents, as a "variable".
02800
02900
03000 3-12. Items do not entirely conform to the structure described
03100 above. Please suppress any enpuzzlement concerning the roles of
03200 items and itemvars until after you have read the paragraph on Item
03300 Declarations, 3-18.
03400
03500
03600 Numeric Declarations
03700
03800
03900 3-13. Identifiers which appear in type declarations with types
04000 REAL or INTEGER can subsequently be used to refer to numeric
04100 variables. An Integer variable may take on values from -2↑35 to
04200 2↑35-1 (-2↑26 to 2↑26-1 for SHORT INTEGERS). A Real variable may
04300 take on positive and negative values from about 10↑-38 to 10↑38 with
04400 a precision of 27 bits (same range for SHORT REALs as for SHORT
04500 INTEGERs. REAL and INTEGER variables (and constants) may be used in
04600 the same arithmetic expressions; type conversions are carried out
04700 automatically (see Arithmetic Type Conversions, 9-21 below) when
04800 necessary.
00100 SAILON NO. 57.2 SAIL 3-14
00200
00300
00400
00500 3-14. The BOOLEAN type is currently identical to INTEGER. As you
00600 will see, BOOLEAN and algebraic expressions are really equivalent
00700 syntactically. The syntactic context in which they appear determines
00800 their meaning. Algorithms for determining the Boolean and algebraic
00900 interpretations of these expressions will be given below. The
01000 declarator BOOLEAN is included for program clarity.
01100
01200
01300 String Declarations
01400
01500
01600 3-15. A variable defined in a String declaration is a two-word
01700 descriptor containing the information necessary to represent a SAIL
01800 character string.
01900
02000
02100 3-16. A String may be thought of as a variable-length,
02200 one-dimensional array of 7-bit ASCII characters. Its descriptor
02300 contains a character count and a byte pointer to the first character
02400 (see STRINGS, 17-15). Strings originate as constants at compile time
02500 (String Constants, 11-19), as the result of a String INPUT operation
02600 from some device (see Input, 12-40), or from the concatenation or
02700 decomposition of already existing strings (see Concatenation
02800 Operator, 9-38 and Substrings, 9-42).
02900
03000
03100 3-17. When strings appear in arithmetic operations or vice-versa,
03200 a somewhat arbitrary conversion is performed to obtain the proper
03300 type (by arbitrary we do not mean to imply random -- see
03400 String-Arithmetic Conversions, 9-27). For this reason arithmetic and
03500 String variables are referred to as "algebraic variables" and their
03600 corresponding expressions are called "algebraic expressions".
03700 (Suggestions for a better term will be given a high priority). No
03800 other direct, or "forced", conversions (except for Integer/Real
03900 conversions) are present in the language.
00100 SAILON NO. 57.2 SAIL 3-18
00200
00300
00400
00500 Item Declarations
00600
00700 Prerequisite
00800
00900
01000 3-18. Please make no attempt to understand the sections of this
01100 manual describing the associative capabilities of the SAIL language
01200 until you have read the article describing its basic flavor in
01300 [Feldman&Rovner]. If you do not have access to a copy of the CACM,
01400 reprints are available from the authors. The structure and
01500 operations of the associative portions of LEAP and SAIL are so nearly
01600 identical that it seemed foolish to repeat them completely here.
01700 However, a full description of the syntax and a brief discussion of
01800 each construct is given here.
01900
02000
02100 Items
02200
02300
02400 3-19. The "Associative memory" of the SAIL system is constructed
02500 from a universe of items and a universe of associations among these
02600 items. An Item is an entity which is represented inside the machine
02700 by its internal name and is otherwise uninterpreted. Items may be
02800 combined to form "associations" which express facts (see Triples,
02900 7-6). They may also be collected into unordered sets (Set
03000 Declarations, 3-24).
03100
03200
03300 Item Genesis
03400
03500
03600 3-20. The universe of items is divided into three classes
03700 differing in the way an Item enters it:
03800
03900 1) A declared Item results from each declaration of an
04000 identifier to be of type ITEM. The declaration causes a
04100 single internal name to be created for the item. Declared
04200 items do not obey the usual rules in recursive functions.
04300 In particular, items behave as if they were declared in the
04400 outer block. Although they may referred to by name only
04500 within the scope of their declarations (see Scope of
04600 declarations, 3-8), they may be accessed from outside the
04700 scope if they have been included in (and not removed from)
04800 any associations or sets, or assigned to itemvars which are
04900 still accessible. They are not deleted at block-exit. It
05000 might be helpful to think of declared items as the
05100 associative analogue of algebraic constants.
00100 SAILON NO. 57.2 SAIL 3-20
00200
00300
00400 2) A created Item results from the execution of a NEW
00500 expression (see NEW Items, 10-6). Any created Item may be
00600 deleted from the universe of items (see DELETE, 7-10).
00700 Again, usual block structure rules do not apply to any
00800 items.
00900
01000 3) An association Item results from the execution of a
01100 bracketed construction triple (see Construction - Retrieval
01200 Distinction, 7-8). These may also be explicitly, but never
01300 automatically, deleted.
01400
01500
01600 Datums
01700
01800
01900 3-21. An Item of type 1) or 2) may have an associated value
02000 (Datum) of algebraic or SET type which can be used or altered like
02100 any other variable. This Datum may represent a simple or array
02200 variable of any type except ITEM or ITEMVAR. Datums may be referred
02300 to by use of the DATUM operator (see Datums, 11-6, Datum Assignments,
02400 4-7).
02500
02600
02700 Itemvar Declarations
02800
02900
03000 3-22. An Itemvar is a variable whose value is an Item (it is a
03100 reference to an Item). Just as the statements "X←3; A←X" and "A←3"
03200 are equivalent with respect to A, the statements "X←EDGE; A←X" and
03300 "A←EDGE" are equivalent with respect to A, if X and A are itemvars,
03400 EDGE an item. The use of an Itemvar is equivalent to the use of the
03500 Item to which it refers. The difference is, of course that the
03600 Itemvars may represent different Items at different times.
03700
03800
03900 3-23. Just as algebraic variables may be bound as loop variables
04000 in FOR statements, Itemvars observe a special binding in the FOREACH
04100 statement. This very important construct is described in FOREACH
04200 Statement, 7-15 below.
00100 SAILON NO. 57.2 SAIL 3-24
00200
00300
00400
00500 Set Declarations
00600
00700
00800 3-24. Because the answers to many associative questions are
00900 many-valued (all the sons of Harry, for example), sets of Items are
01000 provided. A SAIL Set is an unordered collection of Items containing
01100 at most one occurrence of any single Item. The more common Set
01200 operations are available for convenient manipulation of Sets.
01300
01400
01500 Array Declarations
01600
01700
01800 3-25. In general, any data type which is applicable to a simple
01900 variable may be applied in an Array declaration to an array of
02000 variables. Note, however, the restriction (see RESTRICTIONS, 3-2)
02100 prohibiting ITEM ARRAY X as a legal declaration (Items are
02200 "constants"), although ITEMVAR Arrays are allowed. The entity
02300 represented by the name of an Array, qualified with subscript
02400 expressions to locate a particular element (e.g. A[I,J]) behaves in
02500 every way like a simple variable. Therefore, in the future we shall
02600 refer to both simple variables and single elements of Arrays
02700 (subscripted variables) as "variables". The formal syntax for
02800 <variable> can be found in Variables, 11-2.
02900
03000
03100 3-26. Each subscript for an Array which is not qualified by the
03200 SAFE attribute will be checked to ensure that it falls within the
03300 lower and upper bounds given for the dimension it specifies. An
03400 overflow triggers an error message and job abortion. The SAFE
03500 declaration inhibits this checking, resulting in faster, smaller, and
03600 bolder code.
03700
03800
03900 3-27. Arrays are stored by rows. That is, if A[I,J] is stored in
04000 location 10000, then A[I,J+1] is stored in location 10001.
04100
04200
04300 3-28. There is no limit to the number of dimensions allowed for an
04400 Array. However, the efficiency of Array references tends to decrease
04500 for large dimensions. Avoid large dimensionality if it is not
04600 necessary.
00100 SAILON NO. 57.2 SAIL 3-29
00200
00300
00400
00500 3-29. The Item instances stored in an Itemvar Array may have
00600 datums which are themselves algebraic or Set Arrays. This provides a
00700 good deal of power, since an Array of algebraic values can be
00800 dynamically associated with any Item.
00900
01000
01100 3-30. OWN Arrays are available in part. They must be declared
01200 with constant bounds, since fixed storage is allocated for these
01300 Arrays. They are initialized to zero when the block in which they
01400 are declared is entered (except in preloaded Arrays, see Preload
01500 Specifications, 3-33). A certain degree of extra efficiency is
01600 possible in accessing these Arrays, since they may be assigned
01700 absolute core locations by the compiler, eliminating some of the
01800 address arithmetic. Constant bounds always add a little efficiency,
01900 even in inner blocks.
02000
02100
02200 3-31. Arrays declared in the outer block must have constant
02300 bounds, since no variable may yet have been assigned a value. They
02400 are thus automatically made OWN.
02500
02600
02700 3-32. For more details concerning the internal structure of Arrays
02800 see DEBUGGING, 15-9, Separately Compiled Procedures, 16-7 and ARRAY
02900 IMPLEMENTATION, 17-35.
03000
03100
03200 Preload Specifications
03300
03400
03500 3-33. Any OWN arithmetic or String Array may be "pre-loaded" with
03600 constant information by preceding its declaration with a
03700 <preload_specification>. This specification gives the values which
03800 are to be placed in consecutive core locations within all Arrays
03900 declared immediately following the <preload_specification>.
04000 "Immediately", in this case, means all identifiers up to and
04100 including one which is followed by bound_pair_list brackets (e.g. in
04200 REAL ARRAY X,Y,Z[0:10],W[1:5]; -- preloads X,Y, and Z; not W). It is
04300 the user's responsibility to guarantee that the proper values will be
04400 obtained under the subscript mapping.
04500
04600
04700 3-34. The original values of pre-loaded Arrays will not be lost by
04800 restarting the program (most Arrays are cleared when their
04900 declarations are processed), but they will not be re-initialized
05000 either. The values can be changed by assignment statements.
00100 SAILON NO. 57.2 SAIL 3-35
00200
00300
00400
00500 3-35. For String Arrays, the original pre-loaded values remain if
00600 not changed by assignment statements. In general, however, String
00700 Array elements whose values have been changed during program
00800 executions will be set to null strings when the program is restarted.
00900
01000
01100 3-36. Algebraic type conversions will be performed at compile-time
01200 to provide values of the proper types to pre-loaded Arrays. All
01300 expressions in these specifications must be constant expressions --
01400 that is, they must contain only constants and algebraic operators.
01500 The compiler will not allow you to fill an Array beyond its capacity.
01600 You may, however, provide a number of elements less than the total
01700 size of the Array; remaining elements will be set to zero or to the
01800 null string.
01900
02000
02100 Example
02200
02300
02400 3-37.
02500
02600
02700 PRELOAD_WITH [5] 0, 3, 4, [4] 6, 2;
02800 INTEGER ARRAY TABL[1:4,1:3];
02900
03000 The first five elements of TABL will be initialized to 0 (bracketed
03100 number is used as a repeat argument). The next two elements will be
03200 3 and 4, followed by four 6's and a 2. The array will look like
03300 this:
03400
03500
03600 1 2 3
03700
03800 1 0 0 0
03900 2 0 0 3
04000 3 4 6 6
04100 4 6 6 2
04200
00100 SAILON NO. 57.2 SAIL 3-38
00200
00300
00400
00500 Procedure Declarations
00600
00700
00800 3-38. If a Procedure is typed, it may return a value (see Return
00900 Statement, 5-20) of the specified type. If formal parameters are
01000 specified, they must be supplied with actual parameters in a one to
01100 one correspondence when they are called (see Function Designators,
01200 9-47 and Procedure Statements, 6-2).
01300
01400
01500 Formal Parameters
01600
01700
01800 3-39. Formal parameters, when specified, provide information to
01900 the body (executable portion) of the Procedure about the kinds of
02000 values which will be provided as actual parameters in the call. The
02100 type and complexity (simple or Array) are specified here. In
02200 addition, the formal parameter indicates whether the value (VALUE) or
02300 address (REFERENCE) of the actual parameter will be supplied. If the
02400 address is supplied, the variable whose identifier is given as an
02500 actual parameter may be changed by the Procedure. This is not the
02600 case if the value is given.
02700
02800
02900 3-40. To pass a PROCEDURE by value or an ITEM by reference has no
03000 readily determined meaning. ARRAYs passed by value (requiring a
03100 complete copy operation) have not yet been implemented. Therefore
03200 these cases are noted as errors by the compiler.
03300
03400
03500 3-41. The proper use of actual parameters is further discussed in
03600 the paragraphs on Procedure Statements, 6-2 and Function Designators,
03700 9-47.
00100 SAILON NO. 57.2 SAIL 3-42
00200
00300
00400
00500 Forward Procedure Declarations
00600
00700
00800 3-42. A Procedure's type and parameters must be described before
00900 the Procedure may be called. Normally this is accomplished by
01000 specifying the procedure declaration in the head of some block
01100 containing the call. If, however, it is necessary to have two
01200 Procedures, declared in some block head, which are both accessible to
01300 statements in the compound tail of that block and to each other, the
01400 FORWARD construct permits the definition of the parameter information
01500 for one of these Procedures in advance of its declaration. The
01600 Procedure body must be empty in a forward procedure declaration.
01700 When the body of the Procedure described in the forward declaration
01800 is actually declared, the types of the Procedure and of its
01900 parameters must be identical in both declarations. The declarations
02000 must appear at the same level (within the same block head).
00100 SAILON NO. 57.2 SAIL 3-43
00200
00300
00400
00500 Example
00600
00700
00800 3-43.
00900
01000 BEGIN "NEED FORWARD"
01100 FORWARD INTEGER PROCEDURE T1(INTEGER I); COMMENT PARAMS DESCRIBED;
01200
01300 INTEGER PROCEDURE T2(INTEGER J);
01400 RETURN (T1(J)+3); COMMENT CALL T1 ;
01500
01600 INTEGER PROCEDURE T1 (INTEGER I); COMMENT ACTUALLY DEFINE T1;
01700 RETURN (IF I=15 THEN I ELSE T2(I-1)); COMMENT CALLS T2;
01800
01900 ...
02000
02100 K←T1(L); ... ; L←T2(K); ...
02200
02300 END "NEED FORWARD";
02400
02500 Notice that the forward declaration is required only because BOTH
02600 Procedures are called in the body of the block. These procedures
02700 should also be declared RECURSIVE if recursive entrance is likely.
02800 If only T1 were called from statements within the block, this example
02900 could be implemented as:
03000
03100 BEGIN "NO FORWARD"
03200 RECURSIVE INTEGER PROCEDURE T1(INTEGER I);
03300 BEGIN
03400 INTEGER PROCEDURE T2(J);
03500 RETURN (T1(J)+3);
03600
03700 RETURN( IF I=15 THEN I ELSE T2(I-1));
03800 END "T1";
03900
04000 ...
04100 K←T1(L);
04200 ...
04300 END "NO FORWARD";
04400
00100 SAILON NO. 57.2 SAIL 3-44
00200
00300
00400
00500 Recursive Procedures
00600
00700
00800 3-44. If a Procedure is to be entered recursively, the compiler
00900 must be instructed to provide code for saving its local variables
01000 when the Procedure is called and restoring them when it returns. Use
01100 the type-qualifier RECURSIVE in the declaration of any recursive
01200 Procedure.
01300
01400
01500 3-45. The compiler can produce much more efficient code for
01600 non-recursive Procedures than for recursive ones. We feel that this
01700 gain in efficiency merits the necessity for declaring Procedures to
01800 be recursive.
01900
02000
02100 3-46. If a Procedure which has not been declared recursive is
02200 called recursively, all its local variables (and temporary storage
02300 locations assigned by the compiler) will behave as if they were
02400 global to the Procedure -- no values will be saved. Otherwise no ill
02500 effects should be observed.
02600
02700
02800 External Procedures
02900
03000
03100 3-47. A file compiled by SAIL represents either a "main" program
03200 or a collection of independent procedures to be called by the main
03300 program. The method for preparing such a collection of Procedures is
03400 described in Separately Compiled Procedures, 16-7. The EXTERNAL and
03500 FORTRAN type-qualifiers allow description of the types of these
03600 Procedures and their parameters. An EXTERNAL or FORTRAN procedure
03700 declaration, like the FORWARD declaration, does not include a
03800 procedure body. Both declarations instead result in requests to the
03900 loader to provide the addresses of these Procedures to all statements
04000 which call them. This means that an EXTERNAL Procedure declaration
04100 (or the declaration of any External identifier) may be placed within
04200 any block head, thereby controlling the scope of this External
04300 identifier within this program.
04400
04500
04600 3-48. Any SAIL Procedure which is referenced via these external
04700 declarations must be an INTERNAL Procedure. That is, the
04800 type-qualifier INTERNAL must appear in the actual declaration of the
04900 Procedure. Again, see Separately Compiled Procedures, 16-7.
00100 SAILON NO. 57.2 SAIL 3-49
00200
00300
00400
00500 3-49. The type-qualifier FORTRAN is used to describe the type and
00600 name of an external Procedure which is to be called using a DEC
00700 Fortran calling sequence. All parameters to Fortran Procedures are
00800 by reference. In fact, the procedure head part of the declaration
00900 need not be included unless the types expected by the Procedure
01000 differ from those provided by the actual parameters--the number of
01100 parameters supplied, and their types, are presumed correct. Fortran
01200 Procedures are automatically External Procedures. See Restrictions
01300 on Procedure Declarations, 3-54, Procedure Statements, 6-2, Function
01400 Designators, 9-47 for more information about Fortran Procedures.
01500
01600
01700 Example:
01800
01900
02000 3-50.
02100 FORTRAN PROCEDURE MAX;
02200 Y←MAX(X,Z);
02300
02400
02500 Parametric Procedures
02600
02700
02800 3-51. The calling conventions for Procedures with Procedures as
02900 arguments, and for the execution of these parametric Procedures, are
03000 described in Procedure Statements, 6-2 and Function Designators,
03100 9-47. Any Procedure PP which is to be used as a parameter to another
03200 Procedure CP must not have any Procedure or array parameters, or any
03300 parameters called by value. In other words, PP may only have simple
03400 reference parameters. The number of parameters supplied in a call on
03500 PP within CP, and their types, will be presumed correct.
00100 SAILON NO. 57.2 SAIL 3-52
00200
00300
00400
00500 Example
00600
00700
00800 3-52.
00900
01000 PROCEDURE CP (INTEGER PROCEDURE FP);
01100 BEGIN INTEGER A,I; REAL X;
01200 ...
01300 A←FP(I,X); COMMENT I AND X PASSED BY REFERENCE,
01400 NO TYPE CONVERSION;
01500 END "CP";
01600
01700 INTEGER PROCEDURE PP (REFERENCE INTEGER J; REFERENCE REAL Y);
01800 BEGIN
01900 ...
02000 END "PP";
02100
02200 ...
02300
02400 CP(PP);
02500
02600
02700
02800 Defaults in Procedure Declarations
02900
03000
03100 3-53. If no VALUE or REFERENCE qualification appears in the
03200 description, the following qualifications are assumed:
03300
03400
03500 VALUE Variables -- simple INTEGER, STRING, ITEM, ITEMVAR
03600 declarations.
03700
03800 REFERENCE Arrays and Procedures.
03900
04000
04100 Restrictions on Procedure Declarations
04200
04300
04400 3-54.
04500
04600 1) The scope of a formal parameter for a Procedure P does not
04700 include statements within any Procedure Q declared within P. In
04800 other words, Q may refer only to its own formal parameters. It
04900 may, however, refer to variables which are local to some global
05000 Procedure. Here is an example:
00100 SAILON NO. 57.2 SAIL 3-54
00200
00300
00400
00500 PROCEDURE P1(INTEGER I);
00600 BEGIN INTEGER J;
00700 PROCEDURE P2(INTEGER K);
00800 BEGIN
00900 INTEGER L;
01000 L←I; COMMENT THIS IS WRONG -- WON'T WORK;
01100 L←J; COMMENT THIS IS ALL RIGHT;
01200 L←K; COMMENT CLEARLY ALL RIGHT;
01300 ...
01400
01500
01600 2) There is no such thing as an ITEM Procedure (use ITEMVAR).
01700
01800 3) Fortran Procedures can not handle String, Set, or Item
01900 parameters. Nor can a Fortran Procedure return any of these
02000 types as a result.
02100
02200 4) Go To Statements appearing in a Procedure body may not name
02300 statements outside that Procedure body as targets.
02400
02500 5) Labels may never be passed as arguments to Procedures.
02600
02700
02800 Synonyms
02900
03000
03100 3-55. The declaration `LET BEG=BEGIN' would tell the compiler that
03200 BEG is now a reserved word with the same meaning as BEGIN. BEGIN can
03300 subsequently be DEFINEd or declared as something else without
03400 eliminating the opening of new blocks (use BEG for BEGIN). This
03500 synonymity applies only over the scope of the declaration, as usual.
03600
03700
03800 Define Specification
03900
04000
04100 3-56. See the section on USE OF DEFINE, 13-0 for a complete
04200 discussion.
04300
04400
04500 Requirements
04600
04700
04800 3-57. The user may, using the REQUIRE construct, specify to the
04900 compiler conditions which are required to be true of the
05000 execution-time environment of his programs. The requirements fall
05100 into two classifications, described as follows:
00100 SAILON NO. 57.2 SAIL 3-57
00200
00300
00400
00500 Group 1 -- Space requirements -- STRING_SPACE, SYSTEM_PDL, etc.
00600
00700
00800 3-58. The inclusion of the specification "REQUIRE 1000
00900 STRING_SPACE" will ensure that at least 1000 words of storage will be
01000 available for storing Strings when the program is run. Similar
01100 provisions are made for various push-down stacks used by the
01200 execution-time routines and the compiled code. If a parameter is
01300 specified twice, or if separately compiled procedures are loaded (see
01400 Separately Compiled Procedures, 16-7), the sum of all such
01500 specifications will be used. These parameters could also be typed to
01600 the loaded program just before execution (see STORAGE ALLOCATION,
01700 14-22), but it is often more convenient to specify differences from
01800 the standard sizes in the source program. Use these specifications
01900 only if messages from the running program indicate that the standard
02000 allocations are not sufficient. "REQUIRE 300 NEW_ITEMS" specifies
02100 that 300 is a reasonable estimate of the number of items which will
02200 be created dynamically using the NEW construct. "REQUIRE 100 PNAMES"
02300 will allow up to 100 print names to be dynamically assigned to items
02400 (see New_Pname, 12-88, Cvis, 12-84 and following). PNAMES are not
02500 available at all unless some number are "REQUIREd".
02600
02700
02800 Group 2 -- Other files -- LOAD_MODULE, LIBRARY, SOURCE_FILE, etc.
02900
03000
03100 3-59. The inclusion of the specification
03200 REQUIRE "PROCS1" LOAD_MODULE, "HELIB[1,3]" LIBRARY; would inform the
03300 Loader that the file PROCS1.REL must be loaded and the library
03400 HELIB.REL[1,3] searched whenever the program containing the
03500 specification is loaded. The parameter for both features should be a
03600 string constant of one of the above forms. The device DSK, and file
03700 extension .REL are the only values permitted for these entries, and
03800 are therefore assumed.
03900
04000
04100 3-60. LOAD_MODULES (.REL files to be loaded) may themselves
04200 contain requests for other LOAD_MODULES and LIBRARYs. LIBRARYs may
04300 only contain requests for other LIBRARYs. Duplicate specifications
04400 are in general merged into single requests (if a file is requested
04500 twice, it will be loaded only once).
04600
04700
04800 3-61. SAIL automatically places a request for the library
04900 "LIBSAI[1,3]" in each main program. This library contains the
05000 execution-time routines.
00100 SAILON NO. 57.2 SAIL 3-62
00200
00300
00400
00500 3-62. The inclusion of REQUIRE "SYS:PREAMB.SAI" SOURCE_FILE (or,
00600 perhaps, ... "PREAMB.SAI[1,3]" ...) will cause the compiler to save
00700 the state of the current input file, then begin scanning from PREAMB.
00800 When PREAMB is exhausted, SAIL will resume scanning the original file
00900 on the line directly following the REQUIRE. SOURCE_FILEs may be
01000 nested to a depth of about 10 levels.
01100
01200
01300 3-63. Restrictions: A SOURCE_FILE request must be followed by a
01400 semicolon (only one per REQUIREment), and must be the last text on
01500 the line in which it appears. SOURCE_FILE switching must not be
01600 specified from within a DEFINE body.
01700
01800
01900 3-64. The SEGMENT_NAME, SEGMENT_FILE specifications are currently
02000 applicable only to the Stanford "global model" users of SAIL. They
02100 allow specification of the name of a special non-sharable "HISEG",
02200 and the name of the file used to create this HISEG. These
02300 specifications may, like the space REQUIREments, be overridden by
02400 using the system REENTER command (see STORAGE ALLOCATION, 14-22).
02500
02600
02700 Comment
02800
02900
03000 3-65. You have probably noticed that a great deal of prior
03100 knowledge is required for proper understanding of this section. For
03200 more information about PNAMES see Cvis, 12-84 and following. Storage
03300 allocation is discussed in STORAGE ALLOCATION, 14-22 below. The form
03400 and use of .REL files and libraries are described in "The Stanford
03500 A-I Project Monitor Manual" [Moorer] and [Weiher].
00100 SAILON NO. 57.2 SAIL 4-1
00200
00300 SECTION 4
00400
00500 ASSIGNMENT STATEMENTS
00600
00700
00800
00900 SYNTAX
01000
01100
01200 4-1.
01300
01400 <assignment> ::= <assignment_statement>
01500 ::= <swap_statement>
01600
01700 <assignment_statement> ::= <algebraic_assignment>
01800 ::= <item_assignment>
01900 ::= <set_assignment>
02000
02100 <algebraic_assignment> ::= <algebraic_variable> ←
02200 <algebraic_expression>
02300
02400 <item_assignment> ::= <itemvar_variable> ←
02500 <construction_item_expression>
02600
02700 <set_assignment> ::= <set_variable> ←
02800 <construction_set_expression>
02900
03000
03100
03200 <swap_statement> ::= <variable> ↔ <variable>
03300
03400
03500
03600 <byte_statement> ::= DPB (algebraic_expression ,
03700 <algebraic_expression> )
03800 ::= IDPB (algebraic_expression ,
03900 <algebraic_variable> )
04000 ::= IBP (algebraic_variable)
04100
04200
04300
04400 RESTRICTION
04500
04600
04700 4-2. If the operator is ↔, the expression (of whatever kind) on
04800 the right hand side must be a simple or subscripted variable, or
04900 DATUM(<item_primary>). The ↔ operator may not be used in an
05000 assignment expression (see Assignment Expressions, 9-4). It is valid
05100 only at statement level.
00100 SAILON NO. 57.2 SAIL 4-2
00200
00300
00400
00500 SEMANTICS
00600
00700
00800 4-3. The assignment statement causes the value represented by an
00900 expression to be assigned to the variable appearing to the left of
01000 the assignment symbol. You will see later (see Assignment
01100 Expressions, 9-4) that one value may be assigned to two or more
01200 variables through the use of two or more assignment symbols. The
01300 operation of the assignment statement proceeds in the following
01400 order:
01500
01600 a) The subscript expressions of the left part variable (if
01700 any) are evaluated from left to right (see Expression
01800 Evaluation Rules, 9-14).
01900
02000 b) The expression is evaluated.
02100
02200 c) The value of the expression is assigned to the left part
02300 variable, with subscript expressions, if any, having values
02400 as determined in step a.
02500
02600
02700 4-4. This ordering of operations may usually be disregarded.
02800 However it becomes important when expression assignments (Assignment
02900 Expressions, 9-4) or function calls with reference parameters appear
03000 anywhere in the statement. For example, in the statements
03100
03200 I←3;
03300 A[I]←3+(I←1);
03400
03500 A[3] will receive the value 4 using the above algorithm. If no
03600 subscript calculations were performed until after the expression
03700 evaluation, A[1] would become 4. Be careful.
03800
03900
04000 4-5. As the syntax implies, if the left part variable is of type
04100 Itemvar the value to be assigned must be a construction Item
04200 expression. Similarly for Sets.
04300
04400
04500 4-6. However, any algebraic expression (REAL, INTEGER (BOOLEAN),
04600 or STRING) may be assigned to any variable of algebraic type. The
04700 resultant type will be that of the left part variable. The
04800 conversion rules for assignments involving mixed types are mildly
04900 amusing. They are identical to the conversion rules for combining
05000 mixed types in algebraic expressions (see Arithmetic Type Conversions,
05100 9-21, String-Arithmetic Conversions, 9-27 below).
00100 SAILON NO. 57.2 SAIL 4-6
00200
00300
00400
00500 Datum Assignments
00600
00700
00800 4-7. The algebraic or Set value associated with an Item is changed
00900 using an assignment statement in which the left part is a the word
01000 DATUM operating on an Item Primary. This is valid syntactically
01100 because the syntax for <variable> (see Variables, 11-2) includes this
01200 DATUM construct. The expression is checked for validity and proper
01300 type conversions are made before this kind of store occurs. One
01400 hazard is that there are times when the compiler cannot verify that
01500 an Item assigned to an Itemvar has a datum whose type matches that
01600 expected by the Itemvar. Incorrect conversions might well be made in
01700 this case.
01800
01900
02000 Swap Assignment
02100
02200
02300 4-8. The ↔ operator causes the value of the variable on the left
02400 hand side to be exchanged with the value of the variable on the right
02500 hand side. Arithmetic (REAL↔INTEGER) type conversions are made, if
02600 necessary; any other type conversions are invalid. Remember, the ↔
02700 operator may not be used in assignment expressions.
02800
02900
03000 Examples
03100
03200
03300 4-9.
03400
03500 X←I←A+B; Comment if A, B and X are Real, I Integer,
03600 the Real value of the sum is truncated,
03700 converted to an Integer, and stored in I.
03800 The truncated value is then converted to
03900 a Real number and stored in X.
04000
04100 BEGIN REAL ITEMVAR X;
04200 X←LOP(SET3);
04300 DATUM(X) ← 5; Comment a conversion to 5.0 will be made
04400 before the store is done, but there is no guarantee
04500 that the Item obtained by LOP(SET3) was not declared,
04600 for example, as INTEGER ITEM A;
04700 END;
04800
00100 SAILON NO. 57.2 SAIL 4-10
00200
00300
00400
00500 Byte statements
00600
00700
00800 4-10.
00900
01000
01100 4-10. The statements DPB, IDPB and IBP are provided for
01200 manipulating bytes of information. These operations correspond
01300 exactly to the PDP-10 machine instructions for manipulating bytes.
01400 The formats are as follows:
01500
01600 1) DPB ( byte, byte_pointer )
01700 The "byte" is deposited according to the byte_pointer. The
01800 POINT procedure may be used for generating byte pointers
01900 (see Point, 12-126).
02000
02100 2) IDPB ( byte, byte_pointer )
02200 The "byte" is deposited, and the byte_pointer incremented.
02300 For this reason, the byte_pointer may not be an expression,
02400 but must be a variable.
02500
02600 3) IBP ( byte_pointer )
02700 The byte_pointer is incremented. The rules for IDPB apply.
02800
00100 SAILON NO. 57.2 SAIL 5-1
00200
00300 SECTION 5
00400
00500 EXECUTION CONTROL STATEMENTS
00600
00700
00800
00900 SYNTAX
01000
01100
01200 5-1.
01300
01400 <conditional_statement> ::= <if_statement>
01500 ::= <if_statement> ELSE <statement>
01600
01700 <if_statement> ::= IF <boolean_expression> THEN <statement>
01800
01900
02000
02100 <go_to_statement> ::= GO TO <label_identifier>
02200 ::= GOTO <label_identifier>
02300 ::= GO <label_identifier>
02400
02500 <label_identifier> ::= <identifier>
02600
02700
02800
02900 <for_statement> ::= FOR <algebraic_variable> ← <for_list> DO
03000 <statement>
03100 ::= NEEDNEXT <for_statement>
03200
03300 <for_list> ::= <for_list_element>
03400 ::= <for_list> , <for_list_element>
03500
03600 <for_list_element> ::= <algebraic_expression>
03700 ::= <algebraic_expression> STEP
03800 <algebraic_expression> UNTIL
03900 <algebraic_expression>
04000 ::= <algebraic_expression> STEP
04100 <algebraic_expression> WHILE
04200 <boolean_expression>
04300
04400
04500
04600 <while_statement> ::= WHILE <boolean_expression> DO <statement>
04700 ::= NEEDNEXT <while_statement>
04800
04900
00100 SAILON NO. 57.2 SAIL 5-1
00200
00300
00400 <do_statement> ::= DO <statement> UNTIL <boolean_expression>
00500 ::= NEEDNEXT <do_statement>
00600
00700
00800
00900 <case_statement> ::= <case_statement_head> <compound_tail>
01000
01100 <case_statement_head> ::= CASE <algebraic_expression> OF BEGIN
01200
01300
01400
01500 <return_statement> ::= RETURN
01600 ::= RETURN ( <expression> )
01700
01800 <done_statement> ::= DONE
01900 ::= DONE <block_name>
02000
02100 <next_statement> ::= NEXT
02200 ::= NEXT <block_name>
02300
02400 <continue_statement> ::= CONTINUE
02500 ::= CONTINUE <block_name>
02600
02700
02800
02900 SEMANTICS
03000
03100 Conditional Statements
03200
03300
03400 5-2. These statements provide a means whereby the execution of a
03500 statement, or a series of statements, is dependent on the logical
03600 value produced by a Boolean expression.
03700
03800
03900 5-3. A Boolean expression is an algebraic expression whose use
04000 implies that it is to be tested as a logical (truth) value. The
04100 rules for determining this value are given in Simple Expressions, 9-9
04200 and following.
04300
04400
04500 If Statement
04600
04700
04800 5-4. The statement following the operator THEN (the "THEN part") is
04900 executed if the logical value of the Boolean expression is TRUE;
05000 otherwise, that statement is ignored.
00100 SAILON NO. 57.2 SAIL 5-4
00200
00300
00400
00500 If ... Else Statement
00600
00700
00800 5-5. If the Boolean expression is true, the "THEN part" is executed
00900 and the statement following the operator ELSE (the "ELSE part") is
01000 ignored. If the Boolean expression is FALSE, the "ELSE part" is
01100 executed and the "THEN part" is ignored.
01200
01300
01400 Ambiguity in Conditional Statements
01500
01600
01700 5-6. The syntax given here for conditional statements does not
01800 fully explain the correspondences between THEN-ELSE pairs when
01900 conditional statements are nested. An ELSE will be understood to
02000 match the immediately preceding unmatched THEN.
02100
02200
02300 Example
02400
02500
02600 5-7.
02700
02800 COMMENT DECIDE WHETHER TO GO TO WORK;
02900
03000 IF ¬WEEKEND THEN
03100 IF GIANTS_ON_TV THEN BEGIN
03200 PHONE_EXCUSE("GRANDMOTHER DIED");
03300 ENJOY(GAME);
03400 SUFFER(CONSCIENCE_PANGS)
03500 END
03600 ELSE IF REALLY_SICK THEN BEGIN
03700 PHONE_EXCUSE("REALLY SICK");
03800 ENJOY(0);
03900 SUFFER(AGONY)
04000 END
04100 ELSE GO TO WORK;
04200
00100 SAILON NO. 57.2 SAIL 5-8
00200
00300
00400
00500 Go To Statements
00600
00700
00800 5-8. Each of the three forms of the Go To statement means the same
00900 thing -- an unconditional transfer is to be made to the "target"
01000 statement labeled by the label identifier. The following rules
01100 pertain to labels:
01200
01300 1) All label identifiers used in a program must be declared. The
01400 declaration of a label must be local to the block immediately
01500 surrounding the statement it identifies (see exception below).
01600 Note that compound statements (BEGIN-END pairs containing no
01700 declarations) are not blocks. Therefore the block
01800
01900
02000 BEGIN "B1"
02100 INTEGER I,J; LABEL L1;
02200 ...
02300 IF BE3 THEN BEGIN "C1"
02400 ...
02500 L1: ...
02600 ...
02700 END "C1";
02800 ...
02900 GO TO L1
03000 END "B1"
03100
03200 is legal.
03300
03400 2) No Go To Statement may specify a transfer from a statement S1
03500 outside a given block to a target statement S2 inside that
03600 block, if the block contains any Array declarations. This is
03700 automatic from rule 1, since the label identifying S2 is not
03800 available to S1. When no Array declarations are present,
03900 access may be provided by moving the label declaration into
04000 blocks global to the block containing the labelled statement,
04100 as long as the declaration is not made global to a block with
04200 Array declarations, and rule 4 below is followed. Again the
04300 rule does not apply to compound statements, as the above
04400 example demonstrates.
04500
04600 3) No Go To statement may specify a transfer from a statement
04700 within a Procedure to a statement outside that Procedure (you
04800 can't jump out of Procedures).
04900
05000 4) No Go To statement may specify a transfer into a FOREACH
05100 statement, or into complicated For loops (those with For Lists
00100 SAILON NO. 57.2 SAIL 5-8
00200
00300 or which contain a NEXT statement).
00400
00500
00600 5-9. Labels will seldom be needed for debugging purposes. The
00700 block name feature (see DEBUGGING, 15-9) and the listing feature
00800 which associates with each source line the octal address of its
00900 corresponding object code (see Listing Features, 14-13) should
01000 provide enough information to find things easily.
01100
01200
01300 5-10. Many program loops coded with labels can be alternatively
01400 expressed as For or While loops, augmented by DONE, NEXT, and
01500 CONTINUE statements. This often results in a source program whose
01600 organization is somewhat more transparent, and an object program
01700 which is more efficient.
01800
01900
02000 For Statements
02100
02200
02300 5-11. For and While statements (see also FOREACH Statement, 7-15)
02400 provide methods for forming loops in a program. They allow the
02500 repetitive execution of a statement zero or more times. These
02600 statements will be described by means of SAIL programs which are
02700 functionally equivalent but which demonstrate better the actual order
02800 of processing. Refer to these equations for any questions you might
02900 have about what gets evaluated when, and how many times each part is
03000 evaluated.
03100
03200
03300 5-12. Let VBL be any algebraic variable, AE1, ... , AE8 any
03400 algebraic expressions, BE a Boolean expression, TEMP a temporary
03500 location, S a statement. Then the following SAIL statements are
03600 equivalent:
03700
03800
03900 Using For Statements --
04000
04100 FOR VBL ← AE1, AE2, AE3 STEP AE4 UNTIL AE5,
04200 AE6 STEP AE7 WHILE BE, AE8 DO S;
04300
04400
04500 Equivalent formulation without For Statements --
04600
04700 VBL←AE1;
04800 S;
04900 VBL←AE2;
05000 S;
05100
00100 SAILON NO. 57.2 SAIL 5-12
00200
00300
00400 Comment STEP-UNTIL loop;
00500 VBL←AE3;
00600 LOOP1:
00700 IF (VBL-AE5) * SIGN(AE4) ≤ 0 THEN
00800 BEGIN
00900 S;
01000 VBL←VBL+AE4;
01100 GO TO LOOP1
01200 END;
01300
01400
01500 Comment STEP-WHILE loop;
01600 VBL←AE6;
01700 LOOP2:
01800 IF BE THEN BEGIN
01900 S;
02000 VBL←VBL+AE7;
02100 GO TO LOOP2
02200 END;
02300
02400 VBL←AE8;
02500 S;
02600
02700 If AE4 (AE7) is an unsubscripted variable, changing its value within
02800 the loop will cause the new value to be used for the next iteration.
02900 If AE4 (AE7) is a constant or an expression requiring evaluation of
03000 some operator, the value used for the step element will remain
03100 constant throughout the execution of the For Statement. If AE5 is an
03200 expression, it will be re-evaluated before each iteration.
03300
03400
03500 5-13. Now consider the For Statement:
03600
03700 FOR VBL←AE1 STEP CONST UNTIL AE2 DO S;
03800
03900 where const is a positive constant. The compiler will simplify this
04000 case to:
04100
04200
04300 VBL←AE1;
04400 LOOP3:
04500 IF VBL ≤ AE2 THEN BEGIN
04600 S;
04700 VBL←VBL+CONST;
04800 GO TO LOOP3
04900 END;
05000
00100 SAILON NO. 57.2 SAIL 5-13
00200
00300 If CONST is negative, the line at LOOP3 would be:
00400
00500
00600 LOOP3:
00700 IF VBL ≥ AE2 THEN BEGIN
00800
00900
01000
01100 5-14. The value of VBL when execution of the loop is terminated,
01200 whether it be by exhaustion of the for list or by execution of a
01300 DONE,NEXT or GO TO statement (see Done Statement, 5-24,Next
01400 Statement, 5-26,Go To Statements, 5-8), is the value last assigned to
01500 it using the algorithm above. This value is therefore always
01600 well-defined.
01700
01800
01900 5-15. The statement S may contain assignment statements or
02000 procedure calls which change the value of VBL. Such a statement
02100 behaves the same way it would if inserted at the corresponding point
02200 in the equivalent loop described above.
02300
02400
02500 While Statement
02600
02700
02800 5-16. The statement
02900
03000 WHILE BE DO S;
03100
03200 is equivalent to the statements:
03300
03400 LOOP:
03500 IF BE THEN BEGIN
03600 S;
03700 GO TO LOOP
03800 END;
00100 SAILON NO. 57.2 SAIL 5-17
00200
00300
00400
00500 Do Statement
00600
00700
00800 5-17. The statement
00900
01000 DO S UNTIL BE;
01100
01200 is equivalent to the sequence:
01300
01400
01500 LOOP:
01600 S;
01700 IF ¬BE THEN GO TO LOOP;
01800
01900
02000
02100 Case Statements
02200
02300
02400 5-18. The statement
02500
02600 CASE AE OF BEGIN
02700 S0; S1; S2;... Sn
02800 END
02900
03000 is functionally equivalent to the statements:
03100
03200 TEMP←AE;
03300 IF TEMP = 0 THEN S0
03400 ELSE IF TEMP = 1 THEN S1
03500 ELSE IF TEMP = 2 THEN S2
03600 ...
03700 ELSE IF TEMP = n THEN Sn
03800 ELSE ERROR;
03900
04000 For applications of this type the CASE statement form will give
04100 significantly more efficient code than the equivalent If statements.
04200 Notice that dummy statements may be inserted for those cases which
04300 will not occur or for which no entries are necessary. For example,
04400
04500
04600 CASE AE OF BEGIN
04700 S0; ; ; S3; ; ; S6; END
04800
04900 provides for no actions when AE is 1,2,4,5, or 7. When AE is 0, 3,
05000 or 6 the corresponding statement will be executed.
00100 SAILON NO. 57.2 SAIL 5-19
00200
00300
00400
00500 5-19. The CASE statement gives rise to one of the few legitimate
00600 uses of SAIL Labels. If two of the S[i] within a CASE are to do the
00700 same thing except for some initial statements, it is useful to jump
00800 from one into the other (or from both to an unused third) after the
00900 individual code has been executed. If two of the S[i] are to provide
01000 exactly the same functions, it is better to combine them via a
01100 mapping function on the CASE index (e.g., use a character table
01200 containing the same CASE index for all characters which do the same
01300 thing).
01400
01500
01600 Return Statement
01700
01800
01900 5-20. This statement is invalid if it appears outside a procedure
02000 declaration. It provides for an early return from a Procedure
02100 execution to the statement calling the Procedure. If no return
02200 statement is executed, the Procedure will return after the last
02300 statement representing the procedure body is executed (see Procedure
02400 Declarations, 3-38).
02500
02600
02700 5-21. An untyped Procedure (see Procedure Statements, 6-2) may not
02800 return a value. The return statement for this kind of Procedure
02900 consists merely of the word RETURN. If an argument is given, it will
03000 cause the compiler to issue an error message.
03100
03200
03300 5-22. A typed Procedure (see Function Designators, 9-47) must
03400 return a value as it executes a return statement. If no argument is
03500 present an error message will be given. If the Procedure has an
03600 algebraic type, any algebraic expression may be returned as its
03700 value; type conversion will be performed in a manner described by
03800 Arithmetic Type Conversions, 9-21 and String-Arithmetic Conversions,
03900 9-27 below. If the Procedure is of type SET or ITEM, the argument
04000 must be an expression of type SET or ITEM.
04100
04200
04300 5-23. If no RETURN statement is executed in a typed Procedure, the
04400 value returned is undefined (it could be anything -- try it, it's
04500 fun).
00100 SAILON NO. 57.2 SAIL 5-24
00200
00300
00400
00500 Done Statement
00600
00700
00800 5-24. The statement containing only the word DONE may be used to
00900 terminate the execution of a FOR, WHILE, or FOREACH loop explicitly.
01000 Its operation can most easily be seen by means of an example. The
01100 statement
01200
01300
01400 FOR I←1 STEP 1 UNTIL n DO BEGIN
01500 S;
01600 ...
01700 IF BE THEN DONE;
01800 ...
01900 END
02000
02100 is equivalent to the statement
02200
02300 FOR I←1 STEP 1 UNTIL n DO BEGIN
02400 S;
02500 ...
02600 IF BE THEN GO TO EXIT;
02700 ...
02800 END;
02900 EXIT:
03000
03100 In either case the value of I is well-defined after the statement has
03200 been executed (see For Statements, 5-14).
03300
03400
03500 5-25. The DONE statement will only cause an escape from the
03600 innermost loop in which it appears, unless a block name follows
03700 "DONE". The block name must be the name of a block or compound
03800 statement (a "Loop Block") which is the object statement of some FOR,
03900 FOREACH, WHILE, or DO statement in which the current one is nested.
04000 The effect is to terminate all loops out to (and including) the Loop
04100 Block, continuing with the statement following this outermost loop.
00100 SAILON NO. 57.2 SAIL 5-26
00200
00300
00400
00500 Next Statement
00600
00700
00800 5-26. A Next statement is valid only in a For Statement, While
00900 Statement, Do Statement, or Foreach Statement (see For Statements,
01000 5-11, etc., FOREACH Statement, 7-15). Processing of the loop
01100 statement is temporarily suspended. When the NEXT statement appears
01200 in a For or Foreach loop, the next value (set of items) is obtained
01300 from the For List (Associative Context) and assigned to the
01400 controlled variable (bound variables). The termination test is then
01500 made. If the termination condition is satisfied, control is passed
01600 to the statement following the For Statement or Foreach statement.
01700 If not, control is returned to the inner statement following the NEXT
01800 statement. In While and Do loops, the termination condition is
01900 tested. If it is satisfied, execution of the loop terminates.
02000 Otherwise it resumes at the statement within the loop following the
02100 NEXT statement.
02200
02300
02400 5-27. Unless a block name follows NEXT, the innermost loop
02500 containing the NEXT statement is used, and must be preceded by
02600 NEEDNEXT. If a block name is present, the terminating condition for
02700 the loop containing the "Loop Block" (see Done Statement, 5-24,
02800 above) is checked. If the condition is met, all inner loops are
02900 terminated (in DONE fashion) as well. If continuation is indicated,
03000 no inner-loop FOR-variable or WHILE-condition will have been affected
03100 by the NEXT code. In complicated cases, many strange effects will be
03200 noticed.
03300
03400
03500 5-28. The reserved word NEEDNEXT must precede FOREACH, FOR, WHILE,
03600 or DO in the "Loop Block", and must not appear between this block and
03700 the NEXT statement.
03800
03900
04000 Example
04100
04200
04300 5-29.
04400
04500 NEEDNEXT WHILE ¬EOF DO BEGIN
04600 S←INPUT(1,1);
04700 NEXT; Comment check EOF and terminate if TRUE;
04800 T←INPUT(1,3);
04900 PROCESS_INPUT(S,T);
05000 END;
05100
00100 SAILON NO. 57.2 SAIL 5-29
00200
00300
00400
00500 Continue Statement
00600
00700
00800 5-30. The Continue statement is valid in only those contexts valid
00900 for the DONE statement (see Done Statement, 5-24); the "Loop Block"
01000 is determined in the same way. All loops out to the Loop Block are
01100 terminated as if DONE had been requested. Control is transferred to
01200 a point inside the loop containing the Loop Block, but after all
01300 statements in the loop.
01400
01500
01600 Example:
01700
01800
01900 5-31.
02000
02100 FOR I←1 STEP 1 UNTIL N DO BEGIN
02200 ...
02300 CONTINUE;
02400 ...
02500 END
02600
02700 is semantically equivalent to:
02800
02900 FOR I←1 STEP 1 UNTIL N DO BEGIN
03000 LABEL CONT;
03100 ...
03200 GO TO CONT;
03300 ...
03400 CONT:
03500 END
03600
03700
00100 SAILON NO. 57.2 SAIL 6-1
00200
00300 SECTION 6
00400
00500 PROCEDURE STATEMENTS
00600
00700
00800
00900 SYNTAX
01000
01100
01200 6-1.
01300
01400 <procedure_statement> ::= <procedure_identifier>
01500 ::= <procedure_identifier> (
01600 <actual_parameter_list> )
01700
01800 <actual_parameter_list> ::= <actual_parameter>
01900 ::= <actual_parameter_list> ,
02000 <actual_parameter>
02100
02200 <actual_parameter> ::= <expression>
02300 ::= <array_identifier>
02400 ::= <procedure_identifier>
02500
02600
02700
02800 SEMANTICS
02900
03000
03100 6-2. A Procedure statement is used to invoke the execution of an
03200 untyped Procedure (see Procedure Declarations, 3-38). It may also be
03300 used to supply parameters to the Procedure.
03400
03500
03600 6-3. No value may be returned from a Procedure called by a
03700 Procedure statement, since there is no specification in the statement
03800 telling how to use the value. The compiler determines how a
03900 Procedure may be used by noticing if a type was specified in the
04000 procedure declaration. After execution of the Procedure, control
04100 returns to the statement immediately following the Procedure
04200 statement. However, SAIL does allow you to use typed Procedures as
04300 procedure statements. The value returned from the Procedure is
04400 simply discarded.
00100 SAILON NO. 57.2 SAIL 6-4
00200
00300
00400
00500 Actual Parameters
00600
00700
00800 6-4. The actual parameters supplied to a Procedure must in general
00900 match the formal parameters described in the procedure declaration.
01000 As usual, the exception is algebraic expressions; the transfer
01100 functions described in Arithmetic Type Conversions, 9-21 and
01200 String-Arithmetic Conversions, 9-27 will be applied to convert the
01300 type of any algebraic expression passed by VALUE to the algebraic
01400 type required by the Procedure.
01500
01600
01700 Call by Value
01800
01900
02000 6-5. If an actual parameter is passed by VALUE, only the value of
02100 the expression is given to the Procedure. This value may be changed
02200 or examined by the Procedure, but this will in no way affect any of
02300 the variables used to evaluate the actual parameters. Any algebraic
02400 expression, any Item or Set expression may be passed by value.
02500 Neither Arrays nor Procedures may be passed by value. See the
02600 default declarations for parameters in Defaults in Procedure
02700 Declarations, 3-53.
02800
02900
03000 Call by Reference
03100
03200
03300 6-6. If an actual parameter is passed by REFERENCE, its address is
03400 passed to the Procedure. All accesses to the value of the parameter
03500 made by the Procedure are made indirectly through this address.
03600 Therefore any change the Procedure makes in a reference parameter
03700 will change the value of the variable which was used as an actual
03800 parameter. This is sometimes useful. However if it is not intended,
03900 use of this feature can also be somewhat confusing as well as
04000 moderately inefficient. Reference parameters should be used only
04100 where needed.
04200
04300
04400 6-7. Variables, constants, Procedures, Arrays, and most
04500 expressions may be passed by reference. Neither Items nor String
04600 expressions (or String constants) may be reference parameters.
00100 SAILON NO. 57.2 SAIL 6-8
00200
00300
00400
00500 6-8. If an expression is passed by reference, its value is first
00600 placed in a temporary location; a constant passed by reference is
00700 stored in a unique location. The address of this location is passed
00800 to the Procedure. Therefore, any values changed by the Procedure via
00900 reference parameters of this form will be inaccessible to the user
01000 after the Procedure call. If the called program is an assembly
01100 language routine which saves the parameter address, it is dangerous
01200 to pass expressions to it, since this address will be used by the
01300 compiler for other temporary purposes. A warning message will be
01400 printed when expressions are called by reference.
01500
01600
01700 6-9. The type of each actual parameter passed by reference must be
01800 identical to that of its corresponding formal parameter. An
01900 exception is made for Fortran calls (see Fortran Procedures, 6-12).
02000 If an algebraic type mismatch occurs the compiler will create a
02100 temporary variable containing the converted value and pass the
02200 address of this temporary as the parameter. A warning message will
02300 be printed.
02400
02500
02600 Procedures as Actual Parameters
02700
02800
02900 6-10. If an actual parameter to a Procedure PC is the name of a
03000 Procedure PR with no arguments, one of three things might happen:
03100
03200 1) If the corresponding formal parameter requires a value of a
03300 type matching that of PR (in the loose sense given above in
03400 Actual Parameters, 6-4), the Procedure is evaluated and its
03500 value is sent to the Procedure PC.
03600
03700 2) If the formal parameter of PC requires a reference
03800 Procedure of identical type, the address of PR is passed to
03900 PC as the actual parameter.
04000
04100 3) If the formal parameter requires a reference variable, the
04200 Procedure is evaluated, its result stored, and its address
04300 passed (as with expressions in the previous paragraph) as
04400 the parameter.
00100 SAILON NO. 57.2 SAIL 6-11
00200
00300
00400
00500 6-11. If a Procedure name followed by actual parameters appears as
00600 an actual parameter it is evaluated (see Function Designators, 9-47).
00700 Then if the corresponding formal parameter requires a value, the
00800 result of this evaluation is passed as the actual parameter. If the
00900 formal parameter requires a reference to a value, it is called as a
01000 reference expression.
01100
01200
01300 Fortran Procedures
01400
01500
01600 6-12. If the Procedure being called is a Fortran Procedure, all
01700 actual parameters must be of type INTEGER (BOOLEAN) or REAL. All
01800 such parameters are passed by reference, since Fortran will only
01900 accept that kind of call. For convenience, any constant or
02000 expression used as an actual parameter to a Fortran Procedure is
02100 stored in a temporary cell whose address is given as the reference
02200 actual parameter.
02300
02400
02500 6-13. It was explained in Procedure Declarations, 3-38 that formal
02600 parameters need not be described for Fortran Procedures. This allows
02700 a program to call a Fortran Procedure with varying numbers of
02800 arguments, a feature which exists in DEC Fortran. No type conversion
02900 will be performed for such parameters, of course. If type conversion
03000 is desired, the formal parameter declarations should be included in
03100 the Fortran procedure declaration; SAIL will use them if they are
03200 present.
03300
03400
03500 6-14. To pass an Array to Fortran, mention the address of its
03600 first element (e.g. A[0], or B[1,1]).
03700
03800
03900 Implementation Details
04000
04100
04200 6-15. See the paragraphs concerning procedures in the section on
04300 implementation (PROCEDURE IMPLEMENTATION, 17-48) for descriptions of
04400 the calling sequences and basic layout of SAIL procedures. See also
04500 Separately Compiled Procedures, 16-7 for more information about these
04600 useful constructs.
00100 SAILON NO. 57.2 SAIL 6-16
00200
00300
00400
00500 Examples:
00600
00700
00800 6-16. To call an untyped Procedure:
00900
01000 BEGIN ...; PROC(I+J,A[Q],L); ...END;
01100 To call a Procedure of type Integer with one Integer argument:
01200
01300 I←PROC(PROC(I));
01400
00100 SAILON NO. 57.2 SAIL 7-1
00200
00300 SECTION 7
00400
00500 LEAP STATEMENTS
00600
00700
00800
00900 SYNTAX
01000
01100
01200 7-1.
01300
01400 <leap_statement> ::= <set_statement>
01500 ::= <associative_statement>
01600 ::= <loop_statement>
01700
01800 <set_statement> ::= <set_assignment>
01900 ::= PUT <construction_item_expression> IN
02000 <set_variable>
02100 ::= REMOVE <retrieval_item_expression> FROM
02200 <set_variable>
02300
02400 <associative_statement> ::= <item_assignment>
02500 ::= DELETE ( <retrieval_item_expression> )
02600 ::= MAKE <construction_triple>
02700 ::= ERASE <retrieval_triple>
02800
02900
03000
03100 <loop_statement> ::= FOREACH <binding_list>
03200 <associative_context> DO <statement>
03300 ::= NEEDNEXT <loop_statement>
03400
03500 <binding_list> ::= <id_list> |
03600
03700 ::= <id_list> SUCH THAT
03800
03900 <associative_context> ::= <element>
04000 ::= <associative_context> AND <element>
04100 ::= <associative_context> ∧ <element>
04200
04300 <element> ::= <retrieval_associative_expression> IN
04400 <retrieval_set_expression>
04500 ::= <retrieval_triple>
04600 ::= ( <boolean_expression> )
04700
04800 <λ_triple> ::= <λ_derived_set> ≡
04900 <λ_associative_expression>
05000
00100 SAILON NO. 57.2 SAIL 7-1
00200
00300
00400
00500 SEMANTICS
00600
00700 LEAP Introduction
00800
00900
01000 7-2. The basic ALGOL facility in SAIL has been extended with
01100 syntactic constructs and semantic interpretations to reference an
01200 associative data store. This extension was developed by J. Feldman
01300 and P. Rovner and is described in [Feldman]. The LEAP facilities in
01400 SAIL differ slightly from those published in the CACM article. In
01500 the discussion of the use of the associative facilities, reasonably
01600 simple examples are given for each construct. These examples and
01700 associated discussions should emphasize the differences between the
01800 SAIL implementation and the constructs published in the CACM article.
01900
02000
02100 7-3. The LEAP constructs all involve manipulations of one basic
02200 entity, the item. An item is a conceptual entity which is
02300 represented at execution time by a unique number. Associated with
02400 each item in the universe is a DATUM. The DATUM of an item may be an
02500 algebraic quantity, an array of such quantities, or a SET. The DATUM
02600 assignment statement (see Datum Assignments, 4-7) is used to store
02700 the value of an expression into the DATUM of an item. The DATUM of a
02800 declared ARRAY ITEM is loaded automatically when the block in which
02900 the ARRAY ITEM is declared is entered. The DATUM of an item may also
03000 be referenced during evaluation of expressions (see Datums, 11-6).
03100 Examples:
03200 INTEGER ITEM father,joe;
03300 INTEGER ARRAY ITEM ages [1:20];
03400 INTEGER a,b,c;
03500
03600 DATUM (father) ← 21 ;
03700 DATUM (ages) [b] ← b / 33 ;
03800 c ← DATUM (joe) - 12 ;
03900
04000 The DATUM operator is intended to link the powerful associative
04100 processing routines developed for manipulation of items with the
04200 algebraic facilities of ALGOL. This link is made as efficient as
04300 possible -- only two machine instructions are required to access the
04400 DATUM of an item.
00100 SAILON NO. 57.2 SAIL 7-4
00200
00300
00400
00500 7-4. Items or information about items may be stored in a variety
00600 of ways. The simple entity ITEM does not itself occupy storage.
00700 Instead, instances of ITEMS are stored in ITEMVARS, SETS, or
00800 associations. The simplest of these forms is the ITEMVAR: an item
00900 may be "stored" in an ITEMVAR. Evaluation of that ITEMVAR will then
01000 yield the item stored into it. ITEMVARS are thus roughly analogous
01100 to simple arithmetic variables. SAIL also allows arrays of ITEMVARs,
01200 with the obvious interpretation. A typical declaration would be
01300 "ITEMVAR ARRAY x[1:22,0:1]", or "INTEGER ITEMVAR ARRAY y[1:20]".
01400
01500
01600 7-5. Instances of items may also be stored as unordered
01700 collections, or SETS. Facilities are provided for common set
01800 operations (see Set Expressions, 10-2). The SAIL system uses one
01900 word of storage for each item in a set. A set will contain at most
02000 one instance of a specific item: if an instance of item X is already
02100 in set S, then any subsequent attempts to put an instance of X in S
02200 will have no effect. This is in keeping with the standard
02300 mathematical notion of set.
02400
02500
02600 7-6. The third, and perhaps most important, form of storage of
02700 item instances is the association, or triple. Ordered triples of
02800 item instances may be written into or retrieved from a special store,
02900 the associative store. The method of storage of these triples is
03000 designed to facilitate fast and flexible retrieval. SAIL uses
03100 approximately two words of storage for each triple in the associative
03200 store. There is at most one copy of a triple in the store at any
03300 time. Once a triple has been stored in the associative memory, its
03400 component item instances may not be changed. In the examples which
03500 follow, a triple is represented by:
03600
03700 A ⊗ O ≡ V
03800
03900 where A, O, and V are items or itemvars. A, O, and V are mnemonics
04000 for the three components of a triple: attribute, object, and value.
04100 The exact syntactic rules for describing triples are discussed in
04200 SEMANTICS, 10-2.
00100 SAILON NO. 57.2 SAIL 7-7
00200
00300
00400
00500 General Restrictions
00600
00700
00800 7-7. The implementation of the associative store and other forms
00900 of item storage imposes several limitations on the LEAP capability.
01000 The maximum number of items (as represented by their unique numbers)
01100 is 4090. This arises from an overwhelming desire to store a triple
01200 in one word of storage, and hence the requirement that an item number
01300 be describable in 12 bits.
01400
01500
01600 Construction - Retrieval Distinction
01700
01800
01900 7-8. There are two basic operations which are performed on the
02000 three types of item stores -- construction of a new element in that
02100 store, and retrieval of some existing element in the store. For some
02200 purposes, it is necessary to distinguish the operations being
02300 performed. This distinction manages to find its way to the syntax.
02400 In the discussion of associative expressions (Item Constructs, 10-4),
02500 the syntactic forms <construction_item_primary> and
02600 <retrieval_item_primary> are discussed. The ascent from primary
02700 level to associative expressions preserves these distinctions. Thus,
02800 one speaks of a <construction_item_expression>, or of a
02900 <retrieval_item_expression>. Often the BNF productions speak of
03000 <λ_item_expressions>. This is merely a shorthand to denote that two
03100 separate sets of productions exist, one in which λ means
03200 "construction", and one in which λ means "retrieval".
03300
03400
03500 PUT and REMOVE
03600
03700
03800 7-9. The verbs PUT and REMOVE are provided for easily altering
03900 sets. After initialization, all sets are empty. They may be altered
04000 either by PUTting item instances into them or by explicit set
04100 assignment statements. The PUT statement is executed as follows: the
04200 construction item expression is evaluated, and must yield a single
04300 item. An instance of this item is then recorded in the set specified
04400 by the set variable. REMOVE operates in an analogous fashion. If an
04500 instance of the item to be REMOVEd does not occur in the set, an
04600 error message issues forth.
00100 SAILON NO. 57.2 SAIL 7-10
00200
00300
00400
00500 DELETE
00600
00700
00800 7-10. DELETE releases an item from the universe of current items.
00900 Some small amount of storage is reclaimed in this process, as well as
01000 the unique number associated with the item DELETEd. Since there is
01100 an upper limit on the number of items, the DELETE statement can be
01200 used to free item numbers for other uses. The DELETE statement in no
01300 way alters the instances of the DELETEd item which are present in
01400 sets or associations. The user should be sure that there are no
01500 instances of the DELETEd item occurring in sets, itemvars or
01600 associations. Attempts to reference a DELETEd item in any way will
01700 result in confusion.
01800
01900
02000 MAKE
02100
02200
02300 7-11. Associations may be added to the associative memory with the
02400 MAKE statement. If the association already exists in the store, no
02500 alterations are made. The argument to the MAKE statement is a
02600 construction triple; that is, a triple composed of construction
02700 associative expressions. Every construct in these expressions is
02800 interpreted in a construction sense. The component associative
02900 expressions in this triple are evaluated left to right. Some
03000 constructs in these expressions (e.g. see NEW Items, 10-6 or in the
03100 case of bracketed triples) require that new unique item numbers be
03200 created. Examples:
03300
03400 MAKE item1 ⊗ item2 ≡ item3
03500 MAKE item1 ⊗ itemvar1 ≡ NEW
03600 MAKE item1⊗[item2⊗itemvar1≡item3]≡itemvar_array[23]
03700
03800
03900 7-12. The last example involves the use of a BRACKETED TRIPLE.
04000 The bracketed triple "[item2 ⊗ itemvar1 ≡ item]" which is used as an
04100 associative expression is inserted in the associative store. A new
04200 unique item number is generated, which refers to that association.
04300 Various functions ( ISTRIPLE, FIRST, SECOND, THIRD -- see Item
04400 Selectors, 10-5) may use an instance of this new item as their
04500 argument. Consider the following statements:
04600
04700 MAKE number ⊗ [part ⊗ hand ≡ finger] ≡ new (5);
04800 FOREACH x,y SUCH THAT number ⊗ x ≡ y AND
04900 (ISTRIPLE (x) AND FIRST (x) = part) DO
05000 count ← count + DATUM (y) ;
05100
00100 SAILON NO. 57.2 SAIL 7-12
00200
00300
00400
00500 ERASE
00600
00700
00800 7-13. The ERASE statement is provided to undo the damage done by
00900 the MAKE statement. The same general class of arguments must be
01000 provided. ERASE requires a retrieval triple as its argument, thus
01100 eliminating such questionable constructs as NEW from said triples.
01200 However, the construct ANY may appear in a triple specification to
01300 ERASE. This allows a whole slew of appropriate associations to be
01400 erased in one statement. (Restriction: ERASE ANY ⊗ ANY ≡ ANY is
01500 considered bad form, and is as a direct result, forbidden). Sample
01600 ERASE statements are:
01700
01800 ERASE item1 ⊗ item2 ≡ item3
01900 ERASE item1 ⊗ itemvar1 ≡ item2
02000 ERASE itemvar1 ⊗ ANY ≡ item1
02100 RESTRICTION -- MAKE and ERASE will take only item expressions as
02200 arguments, and will not take set expressions.
02300
02400
02500 7-14. In order to give the programmer some idea of what is going
02600 on in the associative store, there is a provision to interrupt each
02700 MAKE and ERASE operation, and enter a breakpoint procedure. This
02800 allows you to get at the attribute, object, and value of the
02900 association being written or erased. ERASE foo ⊗ ANY ≡ ANY will
03000 cause the breakpoint procedure to be activated once for each
03100 association that matches the pattern.
03200
03300 A breakpoint procedure has a declaration of the form:
03400 PROCEDURE breakp ( ITEM a,o,v).
03500 The attribute, object and value of the interrupted operation are
03600 passed in the formal parameters. The breakpoints are set with calls
03700 on two routines in the LEAP runtime routines (they are not
03800 pre-declared, so the appropriate declarations are given below):
03900
04000
04100 EXTERNAL PROCEDURE BRKERS ( PROCEDURE BP );
04200 EXTERNAL PROCEDURE BRKMAK ( PROCEDURE BP );
04300
04400 BRKMAK ( breakp ); Comment this sets the breakpoint for MAKE;
04500 BRKERS ( breakp ); Comment this sets the breakpoint for ERASE;
00100 SAILON NO. 57.2 SAIL 7-15
00200
00300
00400
00500 FOREACH Statement
00600
00700
00800 7-15. Flexible searching and retrieval are the main motivations
00900 for using the set and associative stores. The FOREACH statement
01000 provides this retrieval facility. The FOREACH statement is
01100 essentially a looping statement: the <statement> after the DO is
01200 executed for each group of item instances in the store which
01300 satisfies the FOREACH specification. If there are no such groups
01400 present in the store, the body of the statement is never executed.
01500 The <binding_list> specifies the itemvars which will contain results
01600 of the search. For instance, the simple construct
01700 FOREACH x SUCH THAT x IN set1 DO procedure(x) causes the body of the
01800 statement to be executed once for each item instance in the set set1.
01900 During execution of the body of the statement, the itemvar x
02000 evaluates to the item retrieved from the set set1. Consider,
02100 however, the FOREACH Statement
02200
02300 FOREACH x SUCH THAT x IN set1 AND x IN set2 DO statement
02400
02500 This specification may appear ambiguous, and indeed it is, unless we
02600 define the concept of BINDING the itemvars in a FOREACH
02700 specification. In an associative context, an itemvar which appears
02800 in the <binding_list> is said to be FREE until a search specification
02900 has determined the first requirement on the value of the itemvar (in
03000 a left-to-right scan of the <associative_context>). After the first
03100 requirement, it is said to be BOUND. Thus the <element> in the above
03200 example which reads "x IN set1" specifies a search in which x is
03300 free. The fact that x is free implies the searching operation. In
03400 the second element, "x IN set2", x is bound. Thus no search is
03500 conducted here. Instead, the question "Does an instance of the item
03600 I am considering for x appear in the set set2?" is evaluated. The
03700 answer must be TRUE in order that the statement be executed with x
03800 evaluating to that item. In summary, then, the FOREACH statement
03900 above specifies one search ( x IN set1 ) and one additional
04000 requirement ( x IN set2 ).
00100 SAILON NO. 57.2 SAIL 7-16
00200
00300
00400
00500 7-16. An element of a FOREACH specification may also be a
00600 parenthesized boolean expression. It is of course requisite that all
00700 itemvars appearing in the boolean expression must be bound, i.e. no
00800 searching of the associative store will be accomplished during the
00900 evaluation of the boolean expression. Example:
01000
01100 FOREACH x SUCH THAT x IN set1 AND ( DATUM (x) < 21 ) DO ...
01200
01300 Only members of set1 with DATUMs less than 21 will be selected by
01400 this specification. In the example above (FOREACH Statement, 7-15),
01500 the second <element> could also have been written in its boolean
01600 form: ( x IN set2 ).
01700
01800
01900 7-17. The most powerful <element> construct is a retrieval triple.
02000 Such specifications make searches (for any FREE itemvars) or
02100 verifications (in the case of completely BOUND elements) in the store
02200 of associations. For example:
02300
02400 1. FOREACH x SUCH THAT a ⊗ o ≡ x DO PUT x IN people_set;
02500 2. FOREACH x SUCH THAT a ⊗ o ≡ x AND b ⊗ g ≡ x DO ...
02600
02700 The aim of statement 1 is clear -- a search is conducted through the
02800 associative store for all associations with attribute "a" and object
02900 "o". If k such associations are discovered, then the body of the
03000 statement is executed k times, with x taking on successive values
03100 each time. The second example is similar, but places an additional
03200 constraint on the values of x which should be returned. Since the
03300 second element (b ⊗ g ≡ x) is completely BOUND, no search is
03400 conducted, but a test is made to verify that the association b ⊗ g ≡
03500 x' is in the store, where x' is some item retrieved during the search
03600 for a ⊗ o ≡ x.
03700
03800
03900 7-18. In general, an <associative context> is satisfied by some
04000 assignment of item instances to the itemvars in the <binding list> if
04100 all of the <element>s are satisfied under that assignment. A
04200 <boolean expression> is satisfied if it evaluates to TRUE. A
04300 <retrieval triple> containing no <set expression> is satisfied by an
04400 assignment if the association it specifies is in the universe of
04500 associations. A <retrieval triple> containing a <set expression> (or
04600 ANY) is satisfied if there are, in the universe of associations, any
04700 of the associations formed by substituting elements of the set (or
04800 arbitrary items) in the position occupied by the <set expression>.
00100 SAILON NO. 57.2 SAIL 7-19
00200
00300
00400
00500 7-19. With this concept of SATISFIERS, we proceed to the more
00600 general case with more than one itemvar cited in the binding list.
00700 Suppose there are α such itemvars. Then the <statement> is executed
00800 once for each permutation of the universe of items among the α
00900 itemvars which SATISFY the associative context. During the execution
01000 of the <statement>, the α itemvars will evaluate to the particular
01100 permutation which SATISFIED the associative context.
01200
01300
01400 7-20. The above description for several itemvars is sound but
01500 slightly misleading. The SAIL implementation makes no effort to
01600 avoid duplicating a particular permutation of values which satisfies
01700 the associative context. Thus the <statement> will be executed one
01800 OR MORE times for every permutation which satisfies the associative
01900 context. (See Restrictions and Caveats, 7-22).
00100 SAILON NO. 57.2 SAIL 7-21
00200
00300
00400
00500 7-21. Examples of FOREACH statements with several free itemvars
00600 specified are:
00700
00800 1. FOREACH x,y,z SUCH THAT father⊗x≡y AND father⊗y≡z DO ...
00900 2. FOREACH x,z SUCH THAT father⊗ (father ⊗ x) ≡ z DO ...
01000 3. FOREACH x,y SUCH THAT x IN set AND father ⊗ x ≡ y DO ...
01100 4. FOREACH x,y SUCH THAT father ⊗ x ≡ y AND x IN set DO ...
01200
01300 As it happens, 1 and 2 are equivalent. The compiler actually reduces
01400 2 to 1 by including a dummy itemvar to be analogous to the use of "y"
01500 in the first example. Examples 3 and 4 are precisely equivalent,
01600 that is, the statement will be executed with x and y evaluating to
01700 all the ordered pairs of items which satisfy the (clearly equivalent)
01800 requirements. There is, however, a considerable difference in the
01900 execution efficiency of these two examples. Example 3 is more
02000 efficient since the "set" is probably quite small, and since the
02100 search of the associative memory with only one free itemvar in the
02200 search specification is rather fast. The second example, however,
02300 makes a search through the associative memory for all the (x,y) pairs
02400 and then discards those pairs for which an instance of x does not
02500 occur in the "set". Listed below in order of decreasing efficiency
02600 are the various basic forms of <element>s that are legal. The effect
02700 of a statement such as 2 above should be calculated by reducing it to
02800 the form of 1. In the list below, x, y, and z represent free
02900 itemvars, whereas A, O, and V represent either bound itemvars or
03000 fixed items.
03100
03200 A ⊗ O ≡ V Verification that the triple
03300 is in the store.
03400 A ⊗ O ≡ x Only the value is free.
03500 A IN S Verification that item A is in set S.
03600 x IN S All items x in the set S.
03700 x ⊗ y ≡ V Attribute and object are free.
03800 A ⊗ x ≡ V Only the object is free.
03900 x ⊗ O ≡ V Only the attribute is free.
04000 A ⊗ x ≡ y Object and value are free.
04100 x ⊗ O ≡ y Attribute and value are free.
04200 x ⊗ y ≡ z PROHIBITED
04300
00100 SAILON NO. 57.2 SAIL 7-22
00200
00300
00400
00500 Restrictions and Caveats
00600
00700
00800 7-22. i. The SAIL implementation differs in fundamental ways from
00900 the implementation described by Feldman and Rovner in the CACM
01000 article. Their FOREACH statement builds a record of all the
01100 permutations which satisfy the associative context, being careful to
01200 include only one copy of each such permutation. Then the <statement>
01300 is executed once for each permutation that was stored during the
01400 retrieval operation. The SAIL implementation uses the associative
01500 context as a generator of satisfiers. Thus one group of satisfiers
01600 is found, <statement> is executed for those satisfiers, then another
01700 found, etc. until all groups of satisfiers have been found. The
01800 implications of this method are startling:
01900
02000 1. There is absolutely no way to guarantee that a particular group
02100 of satisfiers is not repeated. There are methods of coding around
02200 this problem. The user can stuff itemvar arrays with results of a
02300 FOREACH and avoid duplications. In many search specifications the
02400 nature of the searches (e.g. sets, where only one copy of an item
02500 instance can occur in the set) avoids duplicate satisfiers.
02600 2. Operations within <statement> which change the associative data
02700 store may affect the subsequent satisfier groups retrieved. Note the
02800 difficulty in the following:
02900
03000 FOREACH x,y |
03100 link ⊗ x ≡ y DO MAKE link ⊗ x ≡ newlink
03200
03300 There is another difficulty with ERASE or REMOVE operations inside a
03400 FOREACH statement. The SAIL implementation saves pointers into the
03500 data structure during the execution of the <statement>. If
03600 operations within that statement cause these pointers to become
03700 invalid, wild effects will occur. Care has been taken, however, to
03800 make sure that some simple things work correctly:
03900
04000 FOREACH x |
04100 link ⊗ x ≡ node DO ERASE link ⊗ x ≡ NODE ;
04200 FOREACH x |
04300 x ε set1 ∧ x ε set2 DO REMOVE x FROM set1 ;
04400 ..... and many more.
00100 SAILON NO. 57.2 SAIL 7-23
00200
00300
00400
00500 7-23. During and after the execution of a FOREACH statement, the
00600 values of the bound itemvars are in general well-defined. They
00700 evaluate to the permutation which last satisfied the FOREACH context.
00800 If a GO TO is executed within the <statement>, the values are correct
00900 in that they correspond to the group of satisfiers for which the
01000 <statement> was being executed. The only case in which the itemvars
01100 are undefined is when the search specified has been exhausted and the
01200 associative context contains a boolean expression. The explanation
01300 of this restriction is quite simple -- prior to the evaluation of a
01400 boolean expression, the core locations reserved for the itemvars in
01500 the <binding_list> are stuffed with the current satisfiers so that
01600 the evaluation of the boolean expression may reference them.
01700
01800
01900 7-24. Expression case statements, conditional expressions, and
02000 procedure calls are all valid within an associative context
02100 specification, provided that all itemvars used in these constructs
02200 are BOUND.
00100 SAILON NO. 57.2 SAIL 8-1
00200
00300 SECTION 8
00400
00500 ASSEMBLY LANGUAGE STATEMENTS
00600
00700
00800
00900 SYNTAX
01000
01100
01200 8-1.
01300
01400 <code_block> ::= <code_head> <code_tail>
01500
01600 <code_head> ::= <code_begin>
01700 ::= <code_begin> <block_name>
01800 ::= <code_head> <declaration> ;
01900
02000 <code_begin> ::= START_CODE
02100 ::= QUICK_CODE
02200
02300 <code_tail> ::= <instruction> END
02400 ::= <instruction> END <block_name>
02500 ::= <instruction> ; <code_tail>
02600
02700 <instruction> ::= <addresses>
02800 ::= <opcode>
02900 ::= <opcode> <addresses>
03000
03100 <addresses> ::= <address>
03200 ::= <ac_field> ,
03300 ::= <ac_field> , <address>
03400
03500 <ac_field> ::= <constant_expression>
03600
03700 <address> ::= <indexed_address>
03800 ::= @ <indexed_address>
03900
04000 <indexed_address> ::= <simple_address>
04100 ::= <simple_address> ( <index_field> )
04200
04300 <simple_address> ::= <identifier>
04400 ::= <constant_expression>
04500 ::= <literal>
04600
04700 <literal> ::= [ <constant_expression> ]
04800
04900 <index_field> ::= <constant_expression>
00100 SAILON NO. 57.2 SAIL 8-1
00200
00300
00400 <opcode> ::= <constant_expression>
00500 ::= PDP-10_opcode
00600
00700
00800
00900 SEMANTICS
01000
01100
01200 8-2. Within a START_CODE (QUICK_CODE) block, statements are
01300 processed by a small and weak, but hopefully adequate, assembly
01400 language translator. Each "instruction" places one instruction word
01500 into the output file.
01600
01700
01800 Declarations in Code Blocks
01900
02000
02100 8-3. A code_block behaves like any other block with respect to
02200 block structure. Therefore, all declarations are valid, and the
02300 names given in these declarations will be available only to the
02400 instructions in the code_block. There will, in general, be more
02500 Labels than usual declared in these blocks, since a Label may appear
02600 in an address field, and since jump instructions referring to such
02700 Labels are the only means for transferring control within a
02800 code_block. Labels in code_blocks may refer to instructions which
02900 will be executed, or to those which are not really instructions, but
03000 data to be manipulated by these instructions (these latter words must
03100 be bypassed in the code by jump instructions).
03200
03300
03400 Meaning of Instruction Operands
03500
03600
03700 8-4. If the <address> in an instruction is a constant (constant
03800 expression), it is assumed to be an immediate or data operand, and is
03900 not relocated. If the <address> is an identifier, the machine
04000 address (relative to the start of the compilation) is used, and will
04100 be relocated to the proper value by the Loader. If the <address> is
04200 an identifier which has been declared as a formal parameter to a
04300 procedure, addressing arithmetic will be done automatically to get at
04400 the VALUE of the paramter. Hence if the <address> is a formal
04500 reference parameter, the instruction will be of the form
04600 OP AC,@ -x('17)
04700 where x depends on exactly where the parameter is in the stack. If a
04800 literal is used, the address of the compiled constant will be placed
04900 in the instruction. Any reference to Strings will result in the
05000 address of the second descriptor word (byte pointer) to be placed in
05100 the instruction.
00100 SAILON NO. 57.2 SAIL 8-5
00200
00300
00400
00500 8-5. The indirect, index, and AC fields have the same syntax and
00600 perform the same functions as they do in the FAIL or MACRO languages.
00700
00800
00900 8-6. The Opcode may be a constant provided by the user, or one of
01000 the standard (non I/O) PDP-10 operation codes, expressed
01100 symbolically. If a constant, it should take the form of a complete
01200 PDP-10 instruction, expressed in octal radix (e.g. DEFINE TTYUUO =
01300 "'510000000000";). Any bits appearing in fields other than the
01400 opcode field (first 9 bits) will be OR'ed with the bits supplied by
01500 other fields of instructions in which this opcode appears.
01600
01700
01800 Distinctions Between START_CODE and QUICK_CODE
01900
02000
02100 8-7. Before your instructions are parsed in a block starting with
02200 START_CODE, instructions are executed to leave all accumulators from
02300 0 through '15 available for your use. In this case, you may use a
02400 JRST to transfer control out of the code_block, as long as you do not
02500 leave a procedure, a block with array declarations, a Foreach loop, a
02600 loop with a For list, or a loop which uses the NEXT construct. In a
02700 QUICK_CODE block, no accumulator-saving instructions are issued.
02800 Ac's '13 through '15 only are free. In addition, some recently used
02900 variables may be given the wrong values if used as address
03000 identifiers (their current values may be contained in Ac's 0-'12);
03100 and control should not leave the code_block except by "falling
03200 through".
03300
03400
03500 Warning Concerning Default Radix
03600
03700
03800 8-8. All integer constants will be expressed in decimal radix
03900 unless the octal representation is explicitly used.
00100 SAILON NO. 57.2 SAIL 9-1
00200
00300 SECTION 9
00400
00500 ALGEBRAIC EXPRESSIONS
00600
00700
00800
00900 SYNTAX
01000
01100
01200 9-1.
01300
01400 <expression> ::= <simple_expression>
01500 ::= <conditional_expression>
01600 ::= <assignment_expression>
01700 ::= <case_expression>
01800
01900
02000
02100 <conditional_expression> ::= IF <boolean_expression> THEN <expression>
02200 ELSE <expression>
02300
02400 <assignment_expression> ::= <assignment_statement>
02500
02600 <case_expression> ::= CASE <algebraic_expression> OF (
02700 <expression_list> )
02800
02900 <expression_list> ::= <expression>
03000 ::= <expression_list> , <expression>
03100
03200 <simple_expression> ::= <algebraic_expression>
03300 ::= <string_expression>
03400 ::= <set_expression>
03500 ::= <associative_expression>
03600
03700 <boolean_expression> ::= <expression>
03800
03900 <string_expression> ::= <algebraic_expression>
04000
04100
04200
04300 <algebraic_expression> ::= <disjunctive_expression>
04400 ::= <algebraic_expression> ∨
04500 <disjunctive_expression>
04600
04700 <disjunctive_expression> ::= <negated_expression>
04800 ::= <disjunctive_expression> ∧
04900 <negated_expression>
00100 SAILON NO. 57.2 SAIL 9-1
00200
00300
00400 <negated_expression> ::= ¬ <relational_expression>
00500 ::= <relational_expression>
00600
00700 <relational_expression> ::= <algebraic_relational>
00800 ::= <leap_relational>
00900
01000 <algebraic_relational> ::= <bounded_expression>
01100 ::= <relational_expression>
01200 <relational_operator>
01300 <bounded_expression>
01400
01500 <leap_relational> ::= <retrieval_item_expression> ε
01600 <retrieval_set_expression>
01700 ::= <retrieval_item_expression>
01800 <relational_operator>
01900 <retrieval_item_expression>
02000 ::= <retrieval_set_expression>
02100 <relational_operator>
02200 <retrieval_set_expression>
02300 ::= <retrieval_triple>
02400
02500 <relational_operator> ::= <
02600 ::= >
02700 ::= =
02800 ::= ≤
02900 ::= ≥
03000 ::= ≠
03100
03200 <bounded_expression> ::= <adding_expression>
03300 ::= <bounded_expression> MAX
03400 <adding_expression>
03500 ::= <bounded_expression> MIN
03600 <adding_expression>
03700
03800 <adding_expression> ::= <term>
03900 ::= <adding_expression> <add_operator> <term>
04000
04100 <adding_operator> ::= +
04200 ::= -
04300 ::= LAND
04400 ::= LOR
04500 ::= EQV
04600 ::= XOR
04700
04800 <term> ::= <factor>
04900 ::= <term> <mult_operator> <factor>
00100 SAILON NO. 57.2 SAIL 9-1
00200
00300
00400 <mult_operator> ::= *
00500 ::= /
00600 ::= %
00700 ::= LSH
00800 ::= ROT
00900 ::= MOD
01000 ::= DIV
01100 ::= &
01200
01300 <factor> ::= <primary>
01400 ::= <primary> ↑ <primary>
01500
01600 <primary> ::= <algebraic_variable>
01700 ::= - <primary>
01800 ::= LNOT <primary>
01900 ::= ABS <primary>
02000 ::= <algebraic_expression> [ <substring_spec>
02100 ]
02200 ::= ∞
02300 ::= <constant>
02400 ::= <function_designator>
02500 ::= ( <algebraic_expression> )
02600 ::= LENGTH ( <retrieval_set_expression> )
02700 ::= LENGTH ( <string_expression> )
02800 ::= CVN ( <item_primary> )
02900 ::= LOP ( <string_variable> )
03000 ::= LDB ( <arithmetic_expression> )
03100 ::= ILDB ( <arithmetic_variable> )
03200 ::= ISTRIPLE ( <item_expression> )
03300
03400 <substring_spec> ::= <algebraic_expression> TO
03500 <algebraic_expression>
03600 ::= <algebraic_expression> FOR
03700 <algebraic_expression>
03800
03900 <function_designator> ::= <procedure_identifier>
04000 ::= <procedure_identifier> (
04100 <actual_parameter_list> )
04200
04300 <actual_parameter_list> ::= <actual_parameter>
04400 ::= <actual_parameter_list> ,
04500 <actual_parameter>
04600
04700 <actual_parameter> ::= <expression>
04800 ::= <array_identifier>
04900 ::= <procedure_identifier>
05000
05100 <algebraic_variable> ::= <variable>
00100 SAILON NO. 57.2 SAIL 9-1
00200
00300
00400 <string_variable> ::= <variable>
00500
00600
00700
00800 SEMANTICS
00900
01000 Conditional Expressions
01100
01200
01300 9-2. A conditional expression returns one of two possible values
01400 depending on the logical truth value of the Boolean expression. For
01500 the rules on evaluation of this truth value see Simple Expressions,
01600 9-9 and following. If the Boolean expression (BE) is true, the value
01700 of the conditional expression is the value of the expression
01800 following the delimiter THEN. If BE is false, the other value is
01900 used. If both expressions are of an algebraic type, the precise type
02000 of the entire conditional expression is that of the "THEN part".
02100 Otherwise, both expressions must be of precisely the same type (Set,
02200 Item, etc.). Unlike the nested If statement problem, there can be no
02300 ambiguity for conditional expressions, since there is an ELSE part in
02400 every such expression.
02500
02600
02700 Example
02800
02900
03000 9-3.
03100
03200 FOURTHDOWN(YARDSTOGO,YARDLINE,IF YARDLINE < 70 THEN PUNT
03300 ELSE IF YARDLINE < 90 THEN FIELDGOAL
03400 ELSE RUNFORIT)
03500
00100 SAILON NO. 57.2 SAIL 9-4
00200
00300
00400
00500 Assignment Expressions
00600
00700
00800 9-4. The somewhat weird syntax for an assignment expression (it is
00900 equivalent to that for an assignment statement) is nonetheless
01000 accurate: the two function identically as far as the new value of the
01100 left part variable is concerned. The difference is that the value of
01200 this left part variable is also retained as the value of the entire
01300 expression. Assuming that the assignment itself is legal (following
01400 the rules given in Assignment Statements, 4-3 above), the type of the
01500 expression is that of the left part variable. This variable may now
01600 participate in any surrounding expressions as if it had been given
01700 its new value in a separate statement on the previous line. Only the
01800 ← operator is valid in assignment expressions. The ↔ operator is
01900 valid only at statement level.
02000
02100
02200 Example
02300
02400
02500 9-5.
02600
02700 IF (I←I+1) < 30 THEN I←0 ELSE I←I+1;
02800
02900
03000
03100 Case Expressions
03200
03300
03400 9-6. The expression
03500
03600
03700 CASE AE OF (E0, E1, E2, ... , En) is equivalent to
03800
03900 IF AE=0 THEN E0
04000 ELSE IF AE=1 THEN E1
04100 ELSE IF AE=2 THEN E2
04200 ...
04300 ELSE IF AE=n THEN En
04400 ELSE ERROR
04500
04600
04700
04800 9-7. The type of the entire expression is therefore that of E0.
04900 If any of the expressions E1 ... En cannot be fit into this mold an
05000 error message is issued by the compiler.
00100 SAILON NO. 57.2 SAIL 9-7
00200
00300
00400
00500 Example
00600
00700
00800 9-8.
00900
01000
01100 OUT(TTY,CASE ERRNO OF("BAD DIRECTORY",
01200 "IMPROPER DATA MODE",
01300 "UNKNOWN I/O ERROR",
01400 ...
01500 "COMPUTER IN BAD MOOD"));
01600
01700
01800
01900 Simple Expressions
02000
02100
02200 9-9. Simple expressions are simple only in that they are not
02300 conditional, case, or assignment expressions. There are in fact some
02400 exciting complexities to be discussed with respect to simple
02500 expressions. Set, Item, and Associative expressions are discussed in
02600 the next section. Before continuing with a description of algebraic
02700 expressions in the following paragraphs, an explanation of what is
02800 meant by a Boolean expression is in order.
02900
03000
03100 The Boolean Expression Anomaly
03200
03300
03400 9-10. You will notice that in the syntax a Boolean expression is
03500 said to be equivalent to an expression. In actuality, the expression
03600 may NOT be an associative one. This is simply a way of expressing
03700 syntactically that there are automatically invoked rules, 1) for
03800 obtaining a logical truth value from an expression which does not
03900 contain any logical operators or logical connectives, and 2) for
04000 obtaining an algebraic (Integer) value from one which does. The
04100 rules are very simple:
00100 SAILON NO. 57.2 SAIL 9-11
00200
00300
00400
00500 Integer, Real, or String to "Boolean"
00600
00700
00800 9-11. The logical truth value of an expression `X' which is of
00900 type Integer, Real, or String is the same as the truth value of the
01000 expression `X≠0'. A String expression will be converted to an
01100 Integer one (see String-Arithmetic Conversions, 9-27) before the
01200 comparison is made. This need not be done for a Real expression, of
01300 course, since the Integer and Real representations for 0 are the
01400 same. This means you can write expressions of the form
01500
01600 IF I+3 THEN E1 ELSE E2 when you really mean
01700 IF I+3≠0 THEN E1 ELSE E2
01800
01900 One application of this rule can be found in several of the execution
02000 time routines (ENTER, LOOKUP, etc.) where an error flag is returned
02100 which is zero (FALSE) if the operation was successful and non-zero
02200 (TRUE) if an error occurred. This flag may be tested as a Boolean
02300 variable (IF FLAG THEN ERROR("LOOKUP FAILED") ) or to determine
02400 exactly what went wrong by examining its actual value.
02500
02600
02700 "Boolean" to Integer
02800
02900
03000 9-12. The truth value of an expression containing logical
03100 operators and/or connectives may be determined by rules given below
03200 (see Algebraic Expressions, 9-15, Disjunctive Expressions, 9-18,
03300 Logical Expressions, 9-31). If this value is needed to determine
03400 which part to execute in a conditional statement, while statement, or
03500 conditional expression no actual numerical value need be created for
03600 the expression -- the tests which determine the truth value lead
03700 directly to the correct program branch. However, if this expression
03800 is combined with other algebraic expressions using some numeric
03900 operator, or if it is assigned to an algebraic variable, some actual
04000 value must be returned for the expression. If the expression is
04100 false, a zero is returned. A non-zero value indicates that the
04200 expression is true. The actual value returned for true expressions
04300 may differ from time to time, but it is guaranteed non-zero.
00100 SAILON NO. 57.2 SAIL 9-13
00200
00300
00400
00500 Precedence of Algebraic Operators
00600
00700
00800 9-13. The binary operators in SAIL generally follow "normal"
00900 precedence rules. That is, exponentiations are performed before
01000 multiplications or divisions, which in turn are performed before
01100 additions and subtractions, etc. The bounding operators MAX and MIN
01200 are performed after these operations. The logical connectives ∧ and
01300 ∨, when they occur, are performed last ( ∧ before ∨). The exact
01400 precedence of operators is described in the syntax above. The order
01500 of operation can be changed by including parentheses at appropriate
01600 points (see Primaries, 9-40).
00100 SAILON NO. 57.2 SAIL 9-14
00200
00300
00400
00500 9-14. In an expression where several operators of the same
00600 precedence occur at the same level, the operations are performed from
00700 left to right. See Algebraic Expressions, 9-15, Disjunctive
00800 Expressions, 9-18 for special evaluation rules for logical
00900 connectives.
01000
01100 Expression Evaluation Rules
01200
01300
01400 9-14. SAIL does not evaluate expressions in a strictly
01500 left-to-right fashion. If we are not constrained to a left-to-right
01600 evaluation, (as is ALGOL 60), we can in some cases produce
01700 considerably better code than a strict left-to-right scheme could
01800 achieve. Intuitively, The essential features (and pitfalls) of this
01900 evaluation rule can be illustrated by a simple example:
02000
02100 REAL PROCEDURE halve ( REFERENCE REAL whole );
02200 RETURN ( whole←whole/2 );
02300
02400 b ← 2.6 ;
02500 c ← b + halve (b) ;
02600
02700 The last assignment statement is evaluated as follows: first call
02800 halve, with a reference to b as its argument; upon return, add b to
02900 the procedure call result; then store the result (which is 2.6) in c.
03000 If we were doing a strict left-to-right evaluation, the value of b
03100 would have to be saved before the procedure halve was called. The
03200 evaluation scheme can be stated quite simply: no code is generated
03300 for the operation represented by a BNF production until the reduction
03400 of that BNF production takes place. The evaluation rules can also be
03500 stated a little more elegantly, by defining a function EVAL whose
03600 value is a REFERENCE to some computed value. EVAL (variable) is a
03700 reference to that variable. EVAL ( thing1 operation thing2 ) is
03800 DO-OPERATION (operation, EVAL(thing1),EVAL(thing2))), where
03900 DO-OPERATION returns a reference to the resulting value. Here
04000 thing1, operation, and thing2 are abstract entities, merely intended
04100 to suggest the various concrete syntactic constructs.
04200
04300
04400 Algebraic Expressions
04500
04600
04700 9-15. If an algebraic expression has as its major connective the
04800 logical connective "∨", the expression has the logical value TRUE
04900 (arithmetic value some non-zero integer) if either of its conjuncts
05000 (the expressions surrounding the "∨") is true; FALSE otherwise.
00100 SAILON NO. 57.2 SAIL 9-16
00200
00300
00400
00500 9-16. A∨B does NOT produce the bit-wise Or of A and B if they are
00600 algebraic expressions. Truth values combined by numeric operators
00700 will in general be meaningless (use the operators LOR and LAND for
00800 bit operations).
00900
01000
01100 9-17. The user should be warned that in an expression containing
01200 logical connectives, only enough of the expression is evaluated (from
01300 left to right) to uniquely determine its truth value. Thus in the
01400 expression
01500
01600 (J<3 ∨ (K←K+1) > 0),
01700
01800 K will not be incremented if J is less than 3 since the entire
01900 expression is already known to be true. Conversely in the expression
02000
02100 (X ≥0 ∧ SQRT(X)>2) (see Disjunctive Expressions, 9-18),
02200
02300 there is never any danger of attempting to extract the square root of
02400 a negative X, since the failure of the first test testifies to the
02500 falsity of the entire expression -- the SQRT routine is not even
02600 called in this case.
02700
02800
02900 Disjunctive Expressions
03000
03100
03200 9-18. If a disjunctive expression has as its major connective the
03300 logical connective "∧", the expression has the logical value TRUE if
03400 both of its disjuncts are TRUE; FALSE otherwise. Again, if the first
03500 disjunct is FALSE a logical value of FALSE is obtained for the entire
03600 expression without further evaluation.
03700
03800
03900 Relational Expressions
04000
04100
04200 9-19. If any of the binary relational operators is encountered,
04300 code is produced to convert any String arguments to Integer numbers.
04400 Then type conversion is done as it is for + operations (see
04500 Arithmetic Type Conversions, 9-21). The values thus obtained are
04600 compared for the indicated condition. A Boolean value TRUE or FALSE
04700 is returned as the value of the expression. Of course, if this
04800 expression is used in subsequent arithmetic operations, a conversion
04900 to integer (see "Boolean" to Integer, 9-12 above) is performed to
05000 obtain an Integer value.
00100 SAILON NO. 57.2 SAIL 9-20
00200
00300
00400
00500 9-20. Leap relational operators are discussed in depth in a later
00600 section.
00700
00800
00900 Arithmetic Type Conversions
01000
01100
01200 9-21. The binary arithmetic, logical, and String operations which
01300 follow will accept combinations of arguments of any algebraic types.
01400 The type of the result of such an operation is sometimes dependent on
01500 the type of its arguments and sometimes fixed. An argument may be
01600 converted to a different algebraic type before the operation is
01700 performed. The following table describes the results of the
01800 arithmetic and logical operations given various combinations of Real
01900 and Integer inputs. ARG1 and ARG2 represent the types of the actual
02000 arguments. ARG1' and ARG2' represent the types of the arguments
02100 after any necessary conversions have been made.
00100 SAILON NO. 57.2 SAIL 9-22
00200
00300
00400
00500 9-22.
00600
00700 OPERATION ARG1 ARG2 ARG1' ARG2' RESULT
00800
00900 + - INT INT INT INT INT*
01000 * ↑ % REAL INT REAL REAL REAL
01100 MAX MIN INT REAL REAL REAL REAL
01200 REAL REAL REAL REAL REAL
01300
01400 LAND LOR INT INT INT INT INT
01500 EQV XOR REAL INT REAL INT REAL
01600 INT REAL INT REAL INT
01700 REAL REAL REAL REAL REAL
01800
01900 LSH ROT INT INT INT INT INT
02000 REAL INT REAL INT REAL
02100 INT REAL INT INT INT
02200 REAL REAL REAL INT REAL
02300
02400 / INT INT REAL REAL REAL
02500 REAL INT REAL REAL REAL
02600 INT REAL REAL REAL REAL
02700 REAL REAL REAL REAL REAL
02800
02900 MOD DIV INT INT INT INT INT
03000 REAL INT INT INT INT
03100 INT REAL INT INT INT
03200 REAL REAL INT INT INT
03300
03400 * Unless ARG2 is <0 for the operator ↑
03500
03600
03700 9-23. An Integer is converted to a Real number in such a way that
03800 if this Real number is converted back to an Integer, the same Integer
03900 value will result, unless the absolute value of the number is greater
04000 than 134217728. Some low-order significance will be lost for
04100 integers greater than this magnitude.
04200
04300
04400 9-24. If the Integer is a SHORT INTEGER variable, or the Real is
04500 SHORT REAL, the conversion is done with a FSC instruction, much more
04600 efficiently (a factor of about 8) than the normal UUO.
00100 SAILON NO. 57.2 SAIL 9-25
00200
00300
00400
00500 9-25. A Real number is converted to an Integer using the following
00600 formula:
00700
00800 Integer ← SIGN(Real)*{largest integer I such that I≤ABS(Real)}.
00900
01000 This function will produce invalid results for Real numbers with a
01100 magnitude greater than 134217728. If either operand is declared
01200 SHORT, conversion is done (Stanford only) with the built-in FIX
01300 instruction, at a correspondingly faster rate. As usual, caution
01400 must be taken that the range of the number is that of a SHORT Integer
01500 (27 bits).
01600
01700
01800 9-26. If a String is presented as an argument to any of these
01900 operations, it is converted to an Integer. If an Integer or Real
02000 argument is presented to the concatenation operator (&), it is
02100 converted to a one-character string. Here are the rules:
02200
02300
02400 String-Arithmetic Conversions
02500
02600
02700 9-27. If a String is presented as an argument to an arithmetic
02800 operator, as a (value) parameter to a procedure which expects a Real
02900 or Integer value, or as an expression to be stored by an assignment
03000 statement into a Real or Integer variable, an Integer value is
03100 created for it as follows:
03200
03300 If the string is the null string (length=0), a 0 is returned as
03400 its `Integer value'. Otherwise a word which has its lefthand 29 bits
03500 0, the rightmost 7 bits containing the first character of the String,
03600 is returned as its `Integer value'. For instance, the String "ABCDE"
03700 has as its `Integer value' '101, the octal representation of the
03800 letter `A'. This Integer will then be converted to a Real number, if
03900 necessary.
00100 SAILON NO. 57.2 SAIL 9-28
00200
00300
00400
00500 9-28. If an Integer or Real number is presented where a String is
00600 expected, a one character String will be created whose character
00700 consists of bits 29-35 (the rightmost seven bits) of the numeric
00800 value. A Real number is not converted to an Integer before the
00900 conversion. For instance, the expression
01000
01100 "STRING"& '15 & '12
01200
01300 will result in a String which is 8 characters long. The last two
01400 characters are the ASCII codes for carriage return and line feed,
01500 respectively.
01600
01700
01800 Bounded Expressions
01900
02000
02100 9-29. A MAX B (where A and B are appropriate expressions -- see
02200 the Syntax) has the value of the larger of A and B (in the algebraic
02300 sense). Type conversions are performed as if the operator were `+'.
02400 0 MAX X MIN 10 is X if 0≤X≤10, 0 if X<0, 10 if X>10.
02500
02600
02700 Adding Expressions
02800
02900
03000 9-30. All the operators grouped in the semantic class
03100 <add_operator> operate at the same precedence level. The user must
03200 sometimes provide parentheses in order to make the meaning of such
03300 expressions absolutely unambiguous. The + and - operators will do
03400 integer addition (subtraction) if both arguments are integers (or
03500 converted to integers from strings); otherwise, rounded Real addition
03600 or subtraction, after necessary conversions, is done.
03700
03800
03900 9-31. LAND, LOR, XOR, and EQV carry out bit-wise And, Or,
04000 Exclusive Or, and Equivalence operations on their arguments. No type
04100 conversions are done for these functions. The logical connectives ∧
04200 and ∨ do not have this effect -- they simply cause tests and jumps to
04300 be compiled. The type of the result is that of the first operand.
04400 This allows expressions of the form X LAND '777777777, where X is
04500 Real, if they are really desired.
04600
04700
04800 9-32. Currently the values of the various overflow flags produced
04900 by these operators (and those which follow) are not available to the
05000 user.
00100 SAILON NO. 57.2 SAIL 9-32
00200
00300
00400
00500 Terms
00600
00700 Arithmetic Multiplicative Operators
00800
00900
01000 9-33. The operation * (multiplication), like + and -, represents
01100 Integer multiplication only if both arguments are integers; Real
01200 otherwise. Integer multiplication uses the IMUL machine instruction
01300 -- no double-length result is available.
01400
01500
01600 9-34. The / operator (division) always does rounded Real division,
01700 after converting any Integer arguments to Real.
01800
01900
02000 9-35. The % operator has the same type table as +, -, and *. It
02100 performs whatever division is appropriate.
02200
02300
02400 9-36. LSH and ROT provide logical shift operations on their first
02500 arguments. If the value of the second argument is positive, a shift
02600 or rotation of that many bits to the left is performed. If it is
02700 negative, a right-shift or rotate is done. To obtain an arithmetic
02800 shift (ASH) operation, multiply or divide by the appropriate power of
02900 2; the compiler will change this operation to a shift operation.
03000
03100
03200 9-37. DIV and MOD force both arguments to be integers before
03300 dividing. X MOD Y is the remainder after X DIV Y is performed
03400 (X MOD Y = X - (X DIV Y)*Y);
03500
03600
03700 Concatenation Operator
03800
03900
04000 9-38. This operator produces a result of type String. It is the
04100 String with length the sum of the lengths of its arguments,
04200 containing all the characters of the second string concatenated to
04300 the end of all the characters of the first. The operands will first
04400 be converted to strings if necessary as described in
04500 String-Arithmetic Conversions, 9-27 above. The normal use of the &
04600 operator is to collect lines of text, from several other string
04700 sources, which will subsequently be sent to an output device.
04800 Numbers can be converted to strings representing their external forms
04900 (and vice-versa) through explicit calls on execution time routines
05000 like CVS and CVD (see Execution Routines, 12-1 below).
00100 SAILON NO. 57.2 SAIL 9-38
00200
00300
00400
00500 Factors
00600
00700
00800 9-39. A factor is either a primary or a primary raised to a power
00900 represented by another primary. As usual, evaluation is from left to
01000 right, so that A↑B↑C is evaluated as (A↑B)↑C. In the factor X↑Y, a
01100 suitable number of multiplications and additions is performed to
01200 produce an "exact" answer if Y is a positive integer. Otherwise a
01300 routine is called to approximate ANTILOG(Y LOG X). The result has
01400 the type of X in the former case. It is always of type Real in the
01500 latter.
01600
01700
01800 Primaries
01900
02000
02100 9-40. A primary represents an arithmetic or String value which
02200 always acts as a unit in any binary operation. It is either an
02300 expression surrounded by parentheses which indicates that all
02400 internal operations should be performed before combining it with
02500 other things, or one of myriad other constructs which will be
02600 considered separately.
02700
02800
02900 Variables and Constants
03000
03100
03200 9-41. These are clearly primary objects. They are values
03300 contained in specific core locations, or in parameter stacks, or in
03400 the case of some numeric constants, they are immediate operands.
03500
03600
03700 Substrings
03800
03900
04000 9-42. A String primary which is qualified by a substring
04100 specification represents a part of the specified string. ST[X FOR Y]
04200 represents the Xth through the (X + Y - 1)th characters of the String
04300 ST. ST[X TO Y] represents the Xth through Yth characters of ST.
00100 SAILON NO. 57.2 SAIL 9-43
00200
00300
00400
00500 9-43. Consider the ST[X TO Y] case. If Y>LENGTH(ST), Y←LENGTH(ST).
00600 if Y<0, Y←0; in either case the right half of the global Integer
00700 _SKIP_ is set to TRUE. If X ≤ 1 it is set to 1. If X > (the
00800 modified) Y, it is set to Y+1 (null string guaranteed). In either
00900 case the left half of _SKIP_ is made TRUE. The ST[X FOR Y] operation
01000 is converted to the ST[X TO Y] case before the substring operation is
01100 performed.
01200
01300
01400 9-44. To examine the above conditions, declare EXTERNAL INTEGER
01500 _SKIP_, and look at it after any interesting substring operation.
01600
01700
01800 Special Length Operator (∞)
01900
02000
02100 9-45. This special primary construct is valid only within
02200 substring brackets. It is an algebraic value representing the length
02300 of the most immediate string under consideration.
02400
02500
02600 Example:
02700
02800
02900 9-46.
03000
03100 A[4 to ∞] throws out the first 3 characters of A.
03200 A[3 for B[∞-1 for 1]] uses the next to the last character
03300 of string B as the number of characters
03400 for the A substring operation.
03500
03600
03700 Function Designators
03800
03900
04000 9-47. A function designator defines a single value. This value is
04100 produced by the execution of a typed user Procedure or of a typed
04200 execution-time routine (Execution Routines, 12-1). For a function
04300 designator to be an algebraic primary, its Procedure must be declared
04400 to have an algebraic type. Untyped Procedures may only be called
04500 from Procedure statements (see Procedure Statements, 6-2). The value
04600 obtained from a user-defined Procedure is that provided by a Return
04700 Statement within that Procedure. If the Procedure does not execute a
04800 Return Statement, the value might be anything at all. A Return
04900 Statement in a typed Procedure must mention a value (see Return
05000 Statement, 5-20).
00100 SAILON NO. 57.2 SAIL 9-48
00200
00300
00400
00500 9-48. The rules for supplying actual parameters in a function
00600 designator are identical to those for supplying parameters in a
00700 procedure statement (see Procedure Statements, 6-2).
00800
00900
01000 9-49. Several of the constructs given here as primaries have the
01100 form of function designators. However, the operations necessary to
01200 obtain the values of these constructs are generally compiled directly
01300 into the program. Descriptions of these functions follow:
01400
01500
01600 Length
01700
01800
01900 9-50. LENGTH is always an integer-valued function. If its
02000 argument is a set expression, the result is the number of Items in
02100 the set. If the argument is a String, its length is the number of
02200 characters in the string. The length of an algebraic expression is
02300 always 1 (see String-Arithmetic Conversions, 9-27).
02400
02500
02600 Lop
02700
02800
02900 9-51. The LOP operator applied to a String variable removes the
03000 first character from the String and returns it in the form given in
03100 String-Arithmetic Conversions, 9-27 above. The String no longer
03200 contains this character. LOP applied to a null String has a zero
03300 value. If the argument is a Set expression the result is an Item.
03400 This case is described below (Item Constructs, 10-4).
03500
03600
03700 Cvn
03800
03900
04000 9-52. CVN has as its value the Integer which is the internal
04100 representation of its Item argument. This function is highly
04200 implementation-dependent, and should only be used by people who are
04300 willing to follow the compiler writers around a lot. Its inverse
04400 function is CVI, described in Item Constructs, 10-4 below.
00100 SAILON NO. 57.2 SAIL 9-53
00200
00300
00400
00500 Lnot
00600
00700
00800 9-53. The unary operator Lnot produces the bitwise complement of
00900 its (algebraic) argument. No type conversions (except strings to
01000 integers) are performed on the argument. The type of the result
01100 (meaningful or not) is the type of the argument.
01200
01300
01400 Abs
01500
01600
01700 9-54. The unary operator ABS is valid only for algebraic
01800 quantities. It returns the absolute value of its argument.
01900
02000
02100 Unary Minus
02200
02300
02400 9-55. -X is equivalent to (0-X). No type conversions are
02500 performed.
02600
02700
02800 Boolean Primaries
02900
03000
03100 9-56. The unary Boolean operator ¬ applied to an argument BE(a
03200 relational expression, see Syntax) has the value TRUE if BE is false,
03300 and FALSE if BE is true. Notice that ¬A is not the bitwise
03400 complement of A, if A is an algebraic value. If used as an algebraic
03500 value, ¬A is simply 0 if A≠0 (see "Boolean" to Integer, 9-12), some
03600 non-zero Integer otherwise.
00100 SAILON NO. 57.2 SAIL 9-57
00200
00300
00400
00500 ISTRIPLE
00600
00700
00800 9-57.
00900
01000
01100 9-57. Istriple (IE) is TRUE if IE is an Item which describes a
01200 bracketed triple. It is FALSE otherwise. If IE is not an Item
01300 expression, the compiler will complain bitterly.
01400
01500 ISTRIPLE ( [A⊗B≡V] ) is true.
01600
01700 ISTRIPLE ( <declared item> ) is false.
01800
01900
02000
02100 LDB and ILDB
02200
02300
02400 9-58. LDB and ILDB are SAIL constructs used to invoke the PDP-10
02500 byte loading instructions. The arguments to these functions are
02600 expressions which are interpreted as byte pointers. In the case of
02700 ILDB, you are required to use an algebraic variable as argument, so
02800 that the byte pointer (i.e. that algebraic variable) may be
02900 incremented.
00100 SAILON NO. 57.2 SAIL 10-1
00200
00300 SECTION 10
00400
00500 SET AND ASSOCIATIVE EXPRESSIONS
00600
00700
00800
00900 SYNTAX
01000
01100
01200 10-1.
01300
01400 <set_expression> ::= <λ_set_expression>
01500
01600 <λ_set_expression> ::= <λ_set_term>
01700 ::= <λ_set_expression> ∪ <λ_set_term>
01800
01900 <λ_set_term> ::= <λ_set_factor>
02000 ::= <λ_set_term> ∩ <λ_set_factor>
02100
02200 <λ_set_factor> ::= <λ_set_primary>
02300 ::= <λ_set_factor> - <λ_set_primary>
02400
02500 <λ_set_primary> ::= PHI
02600 ::= <set_variable>
02700 ::= {λ_item_expr_list}
02800 ::= ( <λ_set_expression> )
02900 ::= <λ_derived_set>
03000
03100 <λ_item_expr_list> ::= <λ_item_expression>
03200 ::= <λ_item_expr_list> , <λ_item_expression>
03300
03400 <λ_derived_set> ::= <λ_associative_expr>
03500 <associative_operator>
03600 <λ_associative_expr>
03700
03800 <associative_operator> ::= ⊗
03900 ::= `
04000 ::= *
04100
04200
04300
04400 <associative_expression> ::= <λ_associative_expr>
04500
04600 <λ_associative_expr> ::= <λ_item_expression>
04700 ::= <λ_set_expression>
00100 SAILON NO. 57.2 SAIL 10-1
00200
00300
00400 <λ_item_expression> ::= <λ_item_primary>
00500 ::= <selector> ( <λ_item_primary> )
00600 ::= [ <λ_item_primary> ⊗ <λ_item_primary> ≡
00700 <λ_item_primary> ]
00800
00900 <construction_item_prim> ::= <item_primary>
01000 ::= NEW
01100 ::= NEW ( <algebraic_expression> )
01200 ::= NEW ( <array_name> )
01300
01400 <retrieval_item_prim> ::= <item_primary>
01500 ::= ANY
01600
01700 <item_primary> ::= <item_identifier>
01800 ::= <itemvar_variable>
01900 ::= CVI ( <algebraic_expression> )
02000 ::= COP ( <set_variable> )
02100 ::= LOP ( <set_variable> )
02200
02300 <λ_triple> ::= <λ_derived_set> ≡
02400 <λ_associative_expression>
02500
02600 <selector> ::= FIRST
02700 ::= SECOND
02800 ::= THIRD
02900
03000 <itemvar_variable> ::= <variable>
03100
03200 <set_variable> ::= <variable>
03300
03400 <leap_relational> ::= <retrieval_associative_expression> IN
03500 <retrieval_set_expression>
03600 ::= <retrieval_associative_expression>
03700 <relational_operator>
03800 <retrieval_associative_expression>
03900 ::= <retrieval_triple>
04000
00100 SAILON NO. 57.2 SAIL 10-2
00200
00300
00400
00500 SEMANTICS
00600
00700 Set Expressions
00800
00900
01000 10-2. Three rather standard operators are implemented for use
01100 with sets. These are union (∪), intersection (∩), and subtraction
01200 (-). These operators have the standard mathematical interpretations.
01300 The only possible confusion pertains to subtraction: if we perform
01400 the set operation set1 - set2, and if there is an instance of an item
01500 x in set2 but not in set1, the subtraction proceeds and no error
01600 message is given.
01700
01800
01900 Set Primaries
02000
02100
02200 10-3. In addition to the <set_variable>, there are three set
02300 primaries: the empty set PHI, a set composed of a list of item
02400 expressions, and derived sets. The empty set is the set with a
02500 LENGTH of 0. Its use is unrestricted. A set primary which results
02600 from a list of item expressions is put together as each item
02700 expression is evaluated. Derived sets are really sets of answers to
02800 questions which search the associative memory. The conventions are:
02900
03000 a ⊗ b -- all x such that a ⊗ b ≡ x
03100 a ` b -- all x such that a ⊗ x ≡ b
03200 a * b -- (a ⊗ b) ∪ (a ` b)
03300
03400 Examples of set primaries:
03500
03600 PHI
03700 { item1 , item2 , itemprocedure1 }
03800 (item1 ⊗ itemvar1)
03900
00100 SAILON NO. 57.2 SAIL 10-4
00200
00300
00400
00500 Item Constructs
00600
00700
00800 10-4. There are several SAIL functions which yield items when
00900 evaluated. This is actually a rather ambiguous statement, since
01000 items as such have no real existence as entities to pass around in
01100 the breeze. But, of course, their unique identifier numbers may be
01200 passed about freely and indeed are, since the identifier number is
01300 sufficient to specify an item. As explained earlier, an itemvar
01400 evaluates to the item last "stored" in that itemvar. There are two
01500 functions provided for removing item instances from sets. The first
01600 of these is COP, which evaluates the <set_expression> argument and
01700 returns an instance of the first item in the set. The "first" item
01800 in a set is not well defined, since the sets are unordered. The
01900 value of the <set_expression> is unchanged. The function LOP is
02000 similar to COP in that its value is an instance of the first item in
02100 the set argument, but the item returned will be removed from the set
02200 if LOP is used. The set argument to LOP must be a <variable> for the
02300 simple reason that the set descriptor must be changed to reflect the
02400 removed item.
02500
02600
02700 Item Selectors
02800
02900
03000 10-5. The operators FIRST, SECOND, and THIRD are provided for
03100 decomposing bracketed triples (see Bracketed Triples, 7-12. The
03200 <item_primary> argument is assumed to be an instance of an item which
03300 was created for the bracketed association when the MAKE was executed.
03400 Examples:
03500 FIRST ( [a⊗o≡v] ) evaluates to a.
03600 SECOND ( [a⊗o≡v] ) evaluates to o.
03700 THIRD ( [a⊗o≡v] ) evaluates to v.
00100 SAILON NO. 57.2 SAIL 10-6
00200
00300
00400
00500 NEW Items
00600
00700
00800 10-6. The function NEW calls upon the associative store to
00900 refurbish a dusty old DELETEd item or to generate a new one. These
01000 new items become a part of the universe of existing items, and may be
01100 accessed and handled in precisely the same fashion as declared items.
01200 If NEW is used in an item expression, that expression is then
01300 constrained to be a construction item expression. NEW may also take
01400 an argument. In this case, the datum of the created item is
01500 preloaded with the value passed as argument. If this argument is
01600 algebraic (real or integer), then the datum will be of the same type.
01700 No type conversions are done when passing the algebraic argument.
01800 NEW will also accept an array name as argument. In this case, the
01900 created item will be of the type array. In fact, the array cited as
02000 argument will be copied into the newly created array. The new array
02100 will have the same bounds and number of dimensions as the array cited
02200 as argument. This array will not disappear even if the outer block
02300 is exited.
02400
02500 NEW_ITEM Declaration
02600
02700
02800 10-6. The SAIL runtime routines allocate several tables based on
02900 the number of items in the world. The maximum size of these tables
03000 is 4096. In order to conserve storage, the size of these tables may
03100 be specified by the user. The compiler accounts for all the declared
03200 items -- it remains the user's responsibility to estimate how many
03300 generated (NEW) items he will require. This specification is made
03400 with the REQUIRE verb:
03500
03600 REQUIRE 2000 NEW_ITEMS;
03700
03800
03900 ANY Construct
04000
04100
04200 10-7. Some associative searches may need only partial
04300 specification -- particular portions of a foreach specification may
04400 be unimportant. The ANY construct is used to specify exactly which
04500 parts of the specification are "don't care"'s. Examples are:
04600
04700 FOREACH x SUCH THAT father ⊗ x ≡ ANY DO PUT x IN sons;
04800 fathers ← (father ⊗ ANY ) ;
04900 ANY is NOT an item. It is merely a syntactic arrangement to specify
05000 the "don't care" condition. Thus foo ← ANY is illegal
00100 SAILON NO. 57.2 SAIL 10-7
00200
00300
00400
00500 CVI
00600
00700
00800 10-8. The function CVI is provided for those people who insist on
00900 having the world at their disposal. The argument is an integer and
01000 the result is an instance of the item which uses that integer as its
01100 unique identifier. Absolutely no error checking is done. CVI is for
01200 daring men.
01300
01400
01500 LEAP Booleans
01600
01700
01800 10-9. Several boolean primaries are implemented for comparing sets
01900 and items. In the following discussion, "ix" means item expression,
02000 and "se" means set expression. These are:
02100 1. Set Membership. The boolean "ix IN se" evaluates the set
02200 expression, and returns TRUE if the item value specified by the item
02300 expression is a member of the set.
02400 2. Association Existence. The boolean " ix ⊗ ix ≡ ix " returns TRUE
02500 if the association exists in the associative store. Examples:
02600
02700 IF father ⊗ x ≡ joe THEN ...
02800 IF father ⊗ joe ≡ ANY THEN MAKE type ⊗ joe ≡ legitimate
02900
03000 3. Relations. The use of the third kind of boolean is more
03100 restricted than the syntax implies. Only the following relations are
03200 valid:
03300
03400 ix = ix -- obvious interpretation
03500 ix ≠ ix -- obvious interpretation
03600 se1 < se2 -- true if se1 is a proper subset of se2
03700 se1 ≤ se2 -- true if se1 is identical to se2 or
03800 if se1 is a proper subset of se2
03900 se1 = se2 -- obvious interpretation
04000 se1 ≠ se2 -- obvious interpretation
04100 se1 > se2 -- equivalent to se2 < se1
04200 se1 ≥ se2 -- equivalent to se2 ≤ se1
04300
04400
00100 SAILON NO. 57.2 SAIL 11-1
00200
00300 SECTION 11
00400
00500 BASIC CONSTRUCTS
00600
00700
00800
00900 SYNTAX
01000
01100
01200 11-1.
01300
01400 <variable> ::= <identifier>
01500 ::= <identifier> [ <subscript_list> ]
01600 ::= DATUM ( <item_identifier> )
01700 ::= DATUM ( <item_identifier> ) [
01800 <subscript_list> ]
01900
02000 <subscript_list> ::= <algebraic_expression>
02100 ::= <subscript_list> , <algebraic_expression>
02200
02300
02400
02500 SEMANTICS
02600
02700 Variables
02800
02900
03000 11-2. If a variable is simply an identifier, it represents a
03100 single value of the type given in its declaration.
03200
03300
03400 11-3. If it is an identifier qualified by a subscript list it
03500 represents an element from the array bearing the name of the
03600 identifier.
00100 SAILON NO. 57.2 SAIL 11-4
00200
00300
00400
00500 11-4. The array should contain as many dimensions as there are
00600 elements in the subscript list. A[I] represents the I+1th element of
00700 the vector A (if the vector has a lower bound of 0). B[I,J] is the
00800 element from the I+1th row and J+1th column of the two-dimensional
00900 array B. To explain the indexing scheme precisely, all arrays behave
01000 as if each dimension had its origin at 0, with (integral) indices
01100 extending infinitely far in either direction. However, only the part
01200 of an array between (and including) the lower and upper bounds given
01300 in the declaration are available for use (and in fact, these are the
01400 only parts allocated). If the array is not declared SAFE, each
01500 subscript is tested against the bounds for its dimension. If it is
01600 outside its range, a fatal message is printed identifying the array
01700 and subscript position at fault. SAFE arrays are not bounds-checked.
01800 Users must take the consequences of the journeys of errant subscripts
01900 for SAFE arrays. The bounds checking causes at least three extra
02000 machine instructions (two of which are always executed for valid
02100 subscripts) to be added for each subscript in each array reference.
02200 The algebraic expressions for lower and upper bounds in array
02300 declarations, and for subscripts in subscripted variables, are always
02400 converted to Integer values (see Arithmetic Type Conversions, 9-21)
02500 before use.
02600
02700
02800 11-5. For more information about the implementation of SAIL
02900 arrays, see ARRAY IMPLEMENTATION, 17-35.
03000
03100
03200 Datums
03300
03400
03500 11-6. If the Item argument of DATUM has an algebraic datum, this
03600 value is returned. Otherwise the result is representative of some
03700 other data type and the value returned will have very little meaning
03800 as an algebraic value; it will probably be some internal pointer or
03900 something. This is mentioned here because there are times when the
04000 compiler will not be able to tell that such a type mismatch has
04100 occurred. Then it will be up to the user to interpret the strange
04200 results. If a Set is desired here, of course, the result is a Set
04300 primary and may be used as such.
04400
04500
04600 Identifiers
04700
04800
04900 11-7. You will notice that no syntax was included for the
05000 non-terminal symbols <identifier> or <constant>. It is far easier to
05100 explain these constructs in an informal manner.
00100 SAILON NO. 57.2 SAIL 11-8
00200
00300
00400
00500 11-8. A SAIL letter is any of the upper or lower case letters A
00600 through Z, or the underline character (_ or !, they are treated
00700 equivalently). Lower case letters are mapped into the corresponding
00800 upper case letters for purposes of symbol table comparisons (SCHLUFF
00900 is the same symbol as Schluff). A digit is any of the characters 0
01000 through 9. An identifier is a string of characters consisting of a
01100 letter followed by virtually any number of letters and digits There
01200 must be a character which is neither a letter nor a digit (nor either
01300 of the characters "." or "$") both before and after every identifier.
01400 In other words, if YOU can't determine where one identifier ends and
01500 another begins in a program you have never seen before, well, neither
01600 can SAIL.
01700
01800
01900 11-9. There is a set of identifiers which are used as SAIL
02000 delimiters (in the Algol sense -- that is, BEGIN is treated by Algol
02100 as if it were a single character. Such an approach is not practical,
02200 so a reserved identifier is used). These identifiers are called
02300 Reserved Words and may not be used for any purpose other than those
02400 given explicitly in the syntax, or in declarations (DEFINES) which
02500 mask their reserved-word status over the scope of the declarations.
02600 E.g., "INTEGER BEGIN" is allowed, but a Synonym (see Synonyms, 3-55)
02700 should have been provided for BEGIN if any new blocks are desired
02800 within this one, because BEGIN is ONLY an Integer in this block.
02900 Another set of identifiers have preset declarations -- these are the
03000 execution time functions. These latter identifiers may also be
03100 redefined by the user; they behave as if they were declared in a
03200 block surrounding the outer block. A list of reserved and
03300 predeclared identifiers follows:
03400
03500
03600 Sail Reserved Words
03700
03800
03900 11-10.
04000
04100 ABS AND ANY ARRAY ARRAY_PDL ASSOC BBPP BEGIN BOOLEAN CASE COMMENT
04200 CONTINUE COP CVI CVN DATUM DEFINE DELETE DIV DO DONE DPB ELSE END
04300 ENTRY EQV ERASE EXTERNAL FALSE FIRST FOR FOREACH FORTRAN FORWARD FROM
04400 GEQ GO GOTO IBP IDPB IF ILDB IN INF INTEGER INTER INTERNAL ISTRIPLE
04500 ITEM ITEMVAR LABEL LAND LDB LENGTH LEQ LET LIBRARY LOAD_MODULE LNOT
04600 LOP LOR LSH MAKE MAX MIN MOD NEEDNEXT NEQ NEXT NEW NEW_ITEMS NOT NULL
04700 OF OR OWN PHI PNAMES PRELOAD_WITH PROCEDURE PUT QUICK_CODE REAL
04800 RECURSIVE REFERENCE REMOVE REQUIRE RETURN ROT SAFE SECOND SET SETC
04900 SETO SHORT SOURCE_FILE START_CODE STEP STRING STRING_PDL STRING_SPACE
05000 SUCH SYSTEM_PDL THAT THEN THIRD TO TRUE UNTIL VALUE WHILE XOR
00100 SAILON NO. 57.2 SAIL 11-11
00200
00300
00400
00500 11-11. Those who use Stanford's "Global Model" compiler will also
00600 recognize:
00700 GLOBAL MESSAGE SEGMENT_FILE SEGMENT_NAME
00800
00900
01000 Sail Predeclared Identifiers
01100
01200
01300 11-12.
01400
01500 ARRBLT ARRINFO ARRTRAN ARRYIN ARRYOUT BREAKSET CALL CLOSE CLOSIN
01600 CLOSO CLRBUF CODE CVASC CVD CVE CVF CVFIL CVG CVIS CVO CVOS CVS CVSI
01700 CVSIX CVSTR CVXSTR ENTER EQU FILEINFO GETCHAN GETFORMAT INCHRW INCHRS
01800 INCHSL INCHWL INSTR INSTRL INSTRS INPUT INTIN INTSCAN LINOUT LOOKUP
01900 MTAPE OPEN OUT OUTCHR OUTSTR REALIN REALSCAN RELEASE RENAME SCAN
02000 SETBREAK SETFORMAT STRBRK TTYIN TTYINL TTYINS WORDIN WORDOUT USERCON
02100 USERERR USETI USETO
02200
02300
02400 11-13. These apply only to Stanford users (especially "Global
02500 Model" users): BACKUP GET_BIT GET_DATA GET_ENTRY IFGLOBAL ISSUE LODED
02600 PTCHRS PTCHRW PTIFRE PTOCNT PTOCHS PTOCHW PTOSTR PTYALL PTYGET PTYIN
02700 PTYREL PTYSTR PUT_DATA QUEUE
00100 SAILON NO. 57.2 SAIL 11-14
00200
00300
00400
00500 11-14. Some of the reserved words are equivalent to certain
00600 special characters. These equivalences are:
00700
00800
00900 CHARACTER RESERVED WORD (s)
01000
01100 ∧ AND
01200 ≡ EQV
01300 ¬ NOT
01400 ∨ OR
01500 ⊗ XOR
01600 ∞ INF
01700 ε IN
01800 | SUCH THAT
01900 ≠ NEQ
02000 ≤ LEQ
02100 ≥ GEQ
02200 { SETO "set open"
02300 } SETC "set close"
02400 ∪ UNION
02500 ∩ INTER
02600 ` ASSOC for derived sets
02700 ↔ SWAP
02800 _ ! alternate underline
02900
03000
03100 Arithmetic Constants
03200
03300
03400 11-15.
03500 12369 is an Integer with decimal value 12369
03600 '12357 is an Integer constant with octal value 12357
03700 123. is a Real constant with floating point value 123.0
03800 0123.0 is a Real constant with floating point value 123.0
03900 .524 is a Real constant with floating point value 0.524
04000 5.3@4 is a Real constant with floating point value 53000.0
04100 5.342@-3 is a Real constant with value 0.005342
04200
04300
04400 11-16. The character ' (right quote) precedes a string of digits
04500 to be converted into an OCTAL number.
00100 SAILON NO. 57.2 SAIL 11-17
00200
00300
00400
00500 11-17. If a . or a @ appears in a numeric constant, the type of
00600 the constant is returned as Real (even if it has an integral value).
00700 Otherwise it is an integer. Type conversions are made at compile
00800 time to make the type of a constant commensurate with that required
00900 by a given operation. Expressions involving only constants are
01000 evaluated by the compiler and the resultant values are substituted
01100 for the expressions.
01200
01300
01400 11-18. The reserved word TRUE is equivalent to the Integer
01500 (Boolean) constant -1; FALSE is equivalent to the constant 0.
01600
01700
01800 String Constants
01900
02000
02100 11-19. A String constant is a string of ASCII characters (any
02200 which you can get into a text file) delimited at each end by the
02300 character ". If the " character is desired in the string, insert two
02400 " characters (after the initial delimiting " character, of course).
02500
02600
02700 11-20. A String constant behaves like any other (algebraic)
02800 primary. It is originally of type String, but may be converted to
02900 Integer by extracting the first character if necessary (see
03000 String-Arithmetic Conversions, 9-27).
03100
03200
03300 11-21. The reserved word NULL represents a String constant
03400 containing no characters (length=0).
00100 SAILON NO. 57.2 SAIL 11-22
00200
00300
00400
00500 Examples
00600
00700
00800 11-22. The left hand column in the table that follows gives the
00900 required input format to obtain the strings given in the right-hand
01000 column:
01100
01200 INPUT RESULT LENGTH
01300
01400 "THIS IS A STRING" THIS IS A STRING 16
01500 "WHAT DOES ""FERNDOK"" MEAN?" WHAT DOES "FERNDOK" MEAN? 25
01600 "THIS IS HOW YOU TYPE A """ THIS IS HOW YOU TYPE A " 24
01700 """THIS IS A QUOTED STRING""" "THIS IS A QUOTED STRING" 25
01800 "" 0
01900 NULL 0
02000
02100
02200
02300 11-23. The scanning algorithm is altered somewhat if the String is
02400 being used as a macro body definition (see USE OF DEFINE, 13-0).
02500
02600
02700 Comments
02800
02900
03000 11-24. If the scanner detects the identifier COMMENT, all
03100 characters up to and including the next semicolon (;) will be
03200 ignored. A comment may appear anywhere as long as the word COMMENT
03300 is properly delimited (not in a String constant, of course);
03400
03500
03600 11-25. A string constant appearing just before a statement also
03700 has the effect of a comment.
00100 SAILON NO. 57.2 SAIL 12-1
00200
00300 SECTION 12
00400
00500 EXECUTION TIME ROUTINES
00600
00700
00800
00900 GENERAL
01000
01100 Scope
01200
01300
01400 12-1. A large set of pre-declared, built-in procedures and
01500 functions have been compiled into a library permanently resident on
01600 the system disk area (SYS:LIBSAI.REL), and optionally into a special
01700 sharable write-protected high segment. The library also contains
01800 programs for managing storage allocation and initialization, and for
01900 certain String functions. If a user calls one of these procedures a
02000 request is automatically made to the loader to include the procedure,
02100 and any other routines it might need, in the core image (or to link
02200 to the high segment). These routines provide input/output (I/O)
02300 facilities, Arithmetic-String conversion facilities, array-handling
02400 procedures and miscellaneous other interesting functions.
02500
02600
02700 12-2. The remainder of this section describes the calling
02800 sequences and functions of these routines.
02900
03000
03100 Notational Conventions
03200
03300
03400 12-3. A short-hand is used in these descriptions for specifying
03500 the types (if any) of the execution-time routines and of their
03600 parameters. Before the description of each routine there is a sample
03700 call of the form
03800
03900
04000 VALUE ← FUNCTION ( ARG1, ARG2, ... ARGn )
04100
04200 If VALUE is omitted, the procedure is an untyped one, and may only be
04300 called at statement level (Procedure Statements, 6-2).
00100 SAILON NO. 57.2 SAIL 12-4
00200
00300
00400
00500 12-4. The types of VALUE and the arguments may be determined using
00600 the following scheme:
00700
00800 1) If " characters surround the sample identifier (which is
00900 usually mnemonic in nature) a String argument is expected.
01000 Otherwise the argument is Integer or Real. If it is
01100 important which of the types Integer or Real must be
01200 presented, it will be made clear in the description of the
01300 function. Otherwise the compiler assumes Integer arguments
01400 (for those functions which are predeclared). The user may
01500 pass Real arguments to these routines (WORDOUT, for example)
01600 by re-declaring them in the blocks in which the Real
01700 arguments are desired.
01800
01900 2) If the @ character precedes the sample identifier, the
02000 argument will be called by reference. Otherwise it is a
02100 value parameter.
02200
02300
02400 Example
02500
02600
02700 12-5.
02800
02900
03000 "RESULT" ← SCAN ( @"SOURCE", BREAK_TABLE, @BRCHAR)
03100
03200 is a predeclared procedure with the implicit declaration:
03300
03400 EXTERNAL STRING PROCEDURE SCAN (REFERENCE STRING SOURCE;
03500 INTEGER BREAK_TABLE;
03600 REFERENCE INTEGER BRCHAR);
03700
03800
03900
04000 I/O ROUTINES
04100
04200
04300 Open ____
04400
04500
04600 Form:
04700
04800
04900 12-6. OPEN(CHANNEL,"DEVICE",MODE,NUMBER_OF_INPUT_BUFFERS,
05000 NUMBER_OF_OUTPUT_BUFFERS,@COUNT,@BRCHAR,@EOF);
00100 SAILON NO. 57.2 SAIL 12-6
00200
00300
00400
00500 Function:
00600
00700
00800 12-7. SAIL input/output operates at a very low level in the
00900 following sense: the operations necessary to obtain devices, open and
01000 close files, etc., are almost directly analogous to the system calls
01100 used in assembly language. OPEN is used to associate a channel
01200 number (0 to '17) with a device, to determine the data mode of the
01300 I/O to occur on this channel (character mode, binary mode, dump mode,
01400 etc.), to specify storage requirements for the data buffers used in
01500 the operations, and to provide the system with information to be used
01600 for input operations.
01700
01800
01900
02000 CHANNEL is a user-provided channel number which will be used in
02100 subsequent I/O operations to identify the device. CHANNEL may
02200 range from 0 to 15 ('17). If some file is already open on
02300 this channel, a RELEASE will be performed for that channel
02400 before the OPEN is executed.
02500
02600
02700 DEVICE must be a String (i.e. "TTY", "DATA") which is recognizable
02800 by the system as a physical or logical device name.
02900
03000
03100 MODE is the data mode for the I/O operation. MODE 0 will always
03200 work for characters ( see Input, 12-40 and Out, 12-45). Modes
03300 8 ('10) and 15 ('17) are applicable for binary and dump-mode
03400 operations using the functions WORDIN, WORDOUT, ARRYIN, or
03500 ARRYOUT (see Wordin, 12-48 and following). For other data
03600 modes, see [Moorer].
03700 If any of bits 18-21 are on in the MODE word, the I-O routines
03800 will not print error messages when data errors occur which
03900 present the corresponding bits as a response to the GETSTS
04000 UUO. Instead, the GETSTS bits will be reported to the user as
04100 described under EOF below. If bit 23 is on, no error message
04200 will be printed if an invalid file name specification is
04300 presented to LOOKUP, ENTER, or RENAME, a code identifying the
04400 problem will be returned (see Lookup, Enter, 12-17 and
04500 following, Rename, 12-21 for details). If you don't
04600 understand any of this, leave all non-mode bits off in the
04700 MODE word.
00100 SAILON NO. 57.2 SAIL 12-7
00200
00300
00400
00500 NUMBER_OF{INPUT/OUTPUT}_BUFFERS specifies the number of buffers to be
00600 reserved for the I/O operations (see [Moorer] for details).
00700 At least one buffer must be specified for input if any input
00800 is to be done in modes other than '17; similarly for output.
00900 If data is only going one direction, the other buffer
01000 specification should be 0. Two buffers give reasonable
01100 performance for most devices (1 is sufficient for a TTY, more
01200 are required for DSK if rapid operation is desired).
01300 The left half of the BUFFER parameter, if non-zero, specifies
01400 the buffer size for the I/O buffers. Use this only if you
01500 desire non-standard sizes.
01600
01700
01800 12-8. The remaining arguments are applicable only for INPUT
01900 (String input). They will be ignored for any other operations
02000 (although their values may be changed by the Open function).
02100
02200
02300 COUNT designates a variable which will contain the maximum number
02400 of characters to be read from "DEVICE" in a given INPUT
02500 call (see Input, 12-40, Breakset, 12-22). Fewer characters
02600 may be read if a break character is encountered or if an
02700 end of file is detected. The count should be a variable or
02800 constant (not an expression), since its address is stored,
02900 and the temporary storage for an expression may be re-used.
03000
03100
03200 BRCHAR designates a variable into which the break character (see
03300 INPUT and BREAKSET again) will be stored. This variable
03400 can be tested to determine which of many possible
03500 characters terminated the read operation.
00100 SAILON NO. 57.2 SAIL 12-8
00200
00300
00400
00500 EOF designates a variable to be used for two purposes:
00600
00700 1) If EOF is 0 when OPEN is called, a SAIL error message will
00800 be invoked if the device is not available. The user will
00900 be given the options of retrying or terminating the
01000 operation. If EOF is non-zero when OPEN is called, it will
01100 be set to 0 if the OPEN is successful. Otherwise it will
01200 not be changed. In this case (EOF non-zero on entry)
01300 control will be returned to the user. This flag may then
01400 be tested.
01500
01600 2) EOF will be made non-zero (TRUE) if an end of file
01700 condition, or any error condition among those enabled (see
01800 MODE, above) is detected during any SAIL input/output
01900 operation. It will be 0 (FALSE) on return to the user
02000 otherwise. Subsequent inputs after an EOF return will
02100 return non-zero values in EOF and a null String result for
02200 INPUT. For ARRYIN , a 0 is returned as the value of the
02300 call after end of file is detected. If EOF is TRUE after
02400 such an operation, it will contain the entire set (18 bits)
02500 of GETSTS information in the left half. The EOF bit is
02600 '20000, and is the only one you'll ever see if you haven't
02700 specially enabled for others. A summary of the enable
02800 bits, the EOF and error bits, and their meanings is
02900 contained in the Appendix NON-FATAL ERROR, EXCEPTIONAL
03000 CONDITION RETURN CODES, 18-11.
03100
03200
03300 Assembly Language Approximation to OPEN
03400
03500
03600 12-9.
03700 INIT CHANNEL,MODE
03800 SIXBIT /DEVICE/
03900 XWD OHED,IHED
04000 JRST <handle error condition>
04100 JUMPE <NUMBER_OF_OUTPUT_BUFFERS>,GETIN
04200 <allocate buffer space>
04300 OUTBUF CHANNEL,NUMBER_OF_OUTPUT_BUFFERS
04400 GETIN: JUMPE <NUMBER_OF_INPUT_BUFFERS>,DONE
04500 <allocate buffer space>
04600 INBUF CHANNEL,NUMBER_OF_INPUT_BUFFERS
04700 DONE: <mark channel open -- internal bookkeeping>
04800 <return>
04900
05000 OHED: BLOCK 3
05100 IHED: BLOCK 3
00100 SAILON NO. 57.2 SAIL 12-9
00200
00300
00400
00500 Close, Closin, Closo ____________________
00600
00700
00800 Form:
00900
01000
01100 12-10.
01200 CLOSE ( CHANNEL )
01300 CLOSIN ( CHANNEL )
01400 CLOSO ( CHANNEL )
01500
01600 Function:
01700
01800
01900 12-10. The input (CLOSIN) or output (CLOSO) side of the specified
02000 channel is closed: all output is forced out (CLOSO); the current file
02100 name is forgotten. However the device is still active; no OPEN need
02200 be done again before the next input/output operation. No INPUT, OUT,
02300 etc. may be given to a directory device until an ENTER, LOOKUP, or
02400 RENAME has been issued for the channel.
02500
02600
02700 12-11. CLOSE is equivalent to the execution of both CLOSIN and
02800 CLOSO for the channel.
02900
03000
03100 Getchan _______
03200
03300
03400 Form:
03500
03600
03700 12-12. VALUE ← GETCHAN;
03800
03900
04000 Function:
04100
04200
04300 12-13. The number of some channel not currently open is returned.
04400 -1 is returned if all channels are busy.
00100 SAILON NO. 57.2 SAIL 12-14
00200
00300
00400
00500 Release _______
00600
00700
00800 Form:
00900
01000
01100 12-14. RELEASE ( CHANNEL );
01200
01300
01400 Function:
01500
01600
01700 12-15. If an OPEN has been executed for this channel, a CLOSE is
01800 now executed for it. The device is dissociated from the channel and
01900 returned to the resource pool (unless it has been assigned by the
02000 monitor ASSIGN command). No I/O operation may refer to this channel
02100 until another OPEN denoting it has been executed.
02200
02300
02400 12-16. Release is always valid. If the channel mentioned is not
02500 currently open, the command is simply ignored.
02600
02700
02800 Lookup, Enter _____________
02900
03000
03100 Form:
03200
03300
03400 12-17.
03500 LOOKUP ( CHANNEL , "FILE" , @FLAG );
03600 ENTER ( CHANNEL , "FILE" , @FLAG );
03700
03800
03900 Function:
04000
04100
04200 12-18. Before input or output operations may be performed for a
04300 directory device (DECtape or DSK) a file name must be associated with
04400 the channel on which the device has been opened (see Open, 12-6).
04500 LOOKUP names a file which is to be read. ENTER names a file which is
04600 to be created or extended (see [Moorer]). Both operations are valid
04700 even if no filename is really necessary. It is recommended that an
04800 ENTER be performed after every OPEN of an output device so that
04900 output not normally directed to the DSK can be directed there for
05000 later processing if desired. The format for a file name string is
00100 SAILON NO. 57.2 SAIL 12-18
00200
00300
00400 NAME ,
00500 NAME.EXT ,
00600 NAME[P,PN] ,
00700 or NAME.EXT[P,PN] (see [Moorer] for the meaning of these things
00800 if you do not immediately understand).
00900
01000 All characters are converted to SIXBIT by moving the '100 bit to the
01100 '40 bit. SAIL is not as choosy about the characters it allows as PIP
01200 and other processors are. Any character which is not ".", ",", "[",
01300 or "]" will be converted and passed on. Up to 6 characters from
01400 NAME, 3 from EXT, P, or PN will be converted -- the rest are ignored.
01500
01600
01700 12-19. If the LOOKUP or ENTER operation fails (see [Moorer]) then
01800 variable FLAG may be examined to determine the cause. The left half
01900 of FLAG will be set to '777777 (Flag has the logical value TRUE).
02000 The right half will contain the code returned by the system giving
02100 the cause of the failure. An invalid file specification will return
02200 a code of '10. In this case, if the appropriate bit (bit 23, see
02300 OPEN) was OFF in the MODE parameter of the OPEN, an error message
02400 will be printed; otherwise, the routine just returns without
02500 performing the UUO.
02600
02700
02800 12-20. If the LOOKUP or ENTER succeeds, FLAG will be set to zero
02900 (FALSE).
03000
03100
03200 Rename ______
03300
03400
03500 Form:
03600
03700
03800 12-21. RENAME ( CHANNEL , "FILE-SPEC" , PROTECTION , @FLAG );
00100 SAILON NO. 57.2 SAIL 12-22
00200
00300
00400
00500 Function:
00600
00700
00800 12-22. The file open on CHANNEL is renamed to FILE_SPEC (a NULL
00900 file-name will delete the file) with read/write protection as
01000 specified in PROTECTION (nine bits, described in the time-sharing
01100 manual). FLAG is set as in LOOKUP and ENTER.
01200
01300
01400 Breakset ________
01500
01600
01700 Form:
01800
01900
02000 12-22. BREAKSET( TABLE, "BREAK_CHARS" , MODE);
02100
02200
02300 Function:
02400
02500
02600 12-23. Character input/output is done using the String features of
02700 SAIL. In fact, I/O is the chief justification for the existence of
02800 strings in the language.
02900 String input presents a problem not present in String output.
03000 The length of an output String can be used to determine the number of
03100 characters written. However it is often awkward to require an
03200 absolute count for input. Quite often one would like to terminate
03300 input, or "break", when one of a specified set of characters is
03400 encountered in the input stream. In SAIL, this capability is
03500 implemented by means of the BREAKSET, INPUT, TTYIN, and SCAN
03600 functions.
03700
03800
03900 12-24. The value of TABLE may range from 1 to 18. Thus up to 18
04000 different sets of break specifications may exist at once. Which set
04100 will be used is determined by the TABLE parameter in an INPUT or SCAN
04200 function call.
04300
04400
04500 12-25. The function of a given BREAKSET command depends on the
04600 MODE, an integer which is interpreted as a right-justified ASCII
04700 character whose value is intended to be vaguely mnemonic. BREAKSET
04800 commands can be partitioned into 3 groups according to mode:
00100 SAILON NO. 57.2 SAIL 12-26
00200
00300
00400
00500 GROUP 1 -- Break character specifications
00600
00700
00800 12-26.
00900
01000
01100 MODE FUNCTION
01200
01300
01400 "I" (by Inclusion) The characters in the BREAK_CHARS String
01500 comprise the set of characters which will terminate an
01600 INPUT (or SCAN).
01700
01800
01900 "X" (by eXclusion) Only those characters (of the possible 128
02000 ASCII characters) which are NOT contained in the String
02100 BREAK_CHARS will terminate an input when using this
02200 table.
02300
02400
02500 "O" (Omit) The characters in "BREAK_CHARS" will be omitted
02600 (deleted) from the input string.
02700
02800
02900 12-27. Any "I" or "X" command completely specifies the break
03000 character set for its table (i.e., the table is reset before these
03100 characters are stored in it). Neither will destroy the omitted
03200 character set currently specified for this table. Any "O" command
03300 completely specifies the set of omitted characters, without altering
03400 the break characters for the table in question. If a character is a
03500 break-character, any role it might play as an omitted character is
03600 sacrificed.
03700
03800
03900 12-28. The second group of MODEs determines the disposition of
04000 break characters in the input stream. The "BREAK_CHARS" argument is
04100 ignored in these commands, and may in fact be NULL:
04200
04300
00100 SAILON NO. 57.2 SAIL 12-29
00200
00300
00400
00500 GROUP 2 -- Break character disposition
00600
00700
00800 12-29.
00900
01000
01100 MODE FUNCTION
01200
01300
01400 "S" (Skip -- default mode) After execution of an "S" command
01500 the break character will not appear either in the
01600 resultant String or in subsequent INPUTs or SCANs-- the
01700 character is "skipped". Its value may be determined
01800 after the INPUT by examination of the break character
01900 variable (see Open, 12-6).
02000
02100
02200 "A" (Append) The break character (if there is one -- see
02300 Open, 12-6 and Input, 12-40) is appended, or
02400 concatenated to the end of the input string. It will
02500 not appear again in subsequent inputs.
02600
02700
02800 "R" (Retain) The break character does not appear in the
02900 resultant INPUT or SCAN String, but will be the first
03000 character processed in the next operation referring to
03100 this input source (file or SCAN String).
03200
03300
03400 12-30. For disk and tape files using the standard editor format,
03500 line numbers present a special problem. A line number is a word
03600 containing 5 ASCII characters representing the number in bits 0-34,
03700 with a "1" in bit 35. No other words in the file contain 1's in bit
03800 35. Since String manipulations provide no way for distinguishing
03900 line numbers from other characters, there must be a way to warn the
04000 user that line numbers are present, or to allow him to ignore them
04100 entirely.
04200
04300
04400 12-31. The third group of MODEs determines the disposition of
04500 these line numbers. Again, the "BREAK_CHARS" argument is ignored:
04600
04700
00100 SAILON NO. 57.2 SAIL 12-32
00200
00300
00400
00500 Group 3 -- Line number disposition
00600
00700
00800 12-32.
00900
01000
01100 MODE FUNCTION
01200
01300
01400 "P" (Pass -- default) Line numbers are treated as any other
01500 characters. Their identity is lost; they simply appear
01600 in the result string.
01700
01800
01900 "N" (No numbers) No line number (or the TAB which always
02000 follows it in standard files) will appear in the result
02100 string. They are simply discarded.
02200
02300
02400 "L" (Line no. break) The result String will be terminated
02500 early if a line number is encountered. The characters
02600 comprising the line number and the associated TAB will
02700 appear as the next 6 characters read or scanned from
02800 this character source. The user's break character
02900 variable (see Open, 12-6 and Input, 12-40) will be set
03000 to -1 to indicate a line number break.
03100
03200
03300 "E" (lee Erman's very own mode) The result String is
03400 terminated on a line number as with "L", but neither the
03500 line number nor the TAB following it will appear in
03600 subsequent inputs. The line number word, negated, is
03700 returned in the user's (integer) BRCHAR variable.
03800
03900
04000 "D" (Display) If the TTY is a DPY, each line number from any
04100 input file will be displayed (along with a page number)
04200 on the right-hand side of the screen. This mode really
04300 applies to all input operations after the "D" operand
04400 appears in any Breakset call. There is no way to turn
04500 it off.
04600
04700
04800 12-33. Once a break table is set up, it may be referenced in an
04900 INPUT, TTYIN or SCAN call to control the scanning operation.
00100 SAILON NO. 57.2 SAIL 12-33
00200
00300
00400
00500 Example:
00600
00700
00800 12-34. To delimit a "word" a program might wish to input
00900 characters until a blank, a TAB, a line feed, a comma, or a semicolon
01000 is encountered, ignoring line numbers. Assume also that carriage
01100 returns are to be ignored, and that the break character is to be
01200 retained in the character source for the next scanning operation:
01300
01400
01500 BREAKSET(DELIMS," ,;"&TAB&LF,"I"); Comment break on any of these;
01600 BREAKSET(DELIMS,'15,"O"); Comment ignore carriage return;
01700 BREAKSET(DELIMS,NULL,"N"); Comment ignore line numbers;
01800 BREAKSET(DELIMS,NULL,"R"); Comment save break char for next time;
01900
02000
02100
02200 Setbreak ________
02300
02400
02500 Form:
02600
02700
02800 12-35.
02900
03000 SETBREAK ( TABLE , "BREAK_CHARS" , "OMIT_CHARS" , "MODES" )
03100
03200
03300 Function:
03400
03500
03600 12-36. SETBREAK is logically equivalent to the SAIL statement:
03700
03800
03900 BEGIN "SETBREAK"
04000 INTEGER I;
04100
04200 IF LENGTH(OMIT_CHARS) > 0 THEN
04300 BREAKSET(TABLE,OMIT_CHARS,"O");
04400
04500 FOR I←1 STEP 1 UNTIL LENGTH(MODES) DO
04600 BREAKSET(TABLE,BREAK_CHARS,MODES[I FOR 1])
04700
04800 END "SETBREAK"
04900
00100 SAILON NO. 57.2 SAIL 12-36
00200
00300
00400
00500 Stdbrk ______
00600
00700
00800 Form:
00900
01000
01100 12-37. STDBRK ( CHANNEL );
01200
01300
01400 Function:
01500
01600
01700 12-38. Eighteen breakset tables have been selected as
01800 representative of the more common input scanning operations. The
01900 function STDBRK initializes the breakset tables by opening the file
02000 SYS:BKTBL.BKT on CHANNEL and reading in these tables. The user may
02100 then reset those tables which he does not like to something he does
02200 like.
02300
02400
02500 12-39. The eighteen tables are described here by giving the
02600 SETBREAKs which would be required for the user to initialize them:
02700
02800
02900 DELIMS ← '15 & '12 & '40 & '11 & '14;
03000 Comment carriage return, line feed, space, tab, form feed;
03100 LETTS ← "ABC ... Zabc ... z_";
03200 DIGS ← "0123456789";
03300 SAILID ← LETTS&DIGS;
03400
03500 SETBREAK ( 1, '12, '15, "INS" );
03600 SETBREAK ( 2, '12, NULL, "INA" );
03700 SETBREAK ( 3, DELIMS, NULL, "XNR" );
03800 SETBREAK ( 4, SAILID, NULL, "INS" );
03900 SETBREAK ( 5, SAILID, NULL, "INR" );
04000 SETBREAK ( 6, LETTS, NULL, "XNR" );
04100 SETBREAK ( 7, DIGS, NULL, "XNR" );
04200 SETBREAK ( 8, DIGS, NULL, "INS" );
04300 SETBREAK ( 9, DIGS, NULL, "INR" );
04400 SETBREAK (10, DIGS&"+-@.", NULL, "XNR" );
04500 SETBREAK (11, DIGS&"+-@.", NULL, "INS" );
04600 SETBREAK (12, DIGS&"+-@.", NULL, "INR" );
04700 SETBREAK (13-18, NULL, NULL, NULL );
04800
00100 SAILON NO. 57.2 SAIL 12-39
00200
00300
00400
00500 Input _____
00600
00700
00800 Form:
00900
01000
01100 12-40. "RESULT" ← INPUT(CHANNEL, BREAK_TABLE);
01200
01300
01400 Function:
01500
01600
01700 12-41. A string of characters is obtained for the file open on
01800 CHANNEL, and is returned as the result. The INPUT operation is
01900 controlled by BREAK_TABLE (see Breakset, 12-22) and the reference
02000 variables BRCHAR, EOF, and COUNT which are provided by the user in
02100 the OPEN function for this channel (see Open, 12-6). Input may be
02200 terminated in several ways. The exact reason for termination can be
02300 obtained by examining BRCHAR and EOF:
00100 SAILON NO. 57.2 SAIL 12-41
00200
00300
00400
00500
00600 EOF BRCHAR
00700
00800
00900 ≠0 0 End of file or an error (if enabled, see Open, 12-6
01000 occurred while reading. The result is a String
01100 containing all non-omitted characters which
01200 remained in the file when INPUT was called.
01300
01400
01500 0 0 No break characters were encountered. The result
01600 is a String of length equal to the current COUNT
01700 specifications for the CHANNEL (see Open, 12-6).
01800
01900
02000 0 <0 A line number was encountered and the break table
02100 specified that someone wanted to know. The result
02200 String contains all characters up to the line
02300 number. If mode "L" was specified in the Breakset
02400 setting up this table, bit 35 is turned off in the
02500 line number word so that it will be input next
02600 time. -1 is placed in BRCHAR. If mode "E" was
02700 specified, the line number will not appear in the
02800 next input String, but its negated ASCII value,
02900 complete with low-order line number bit, will be
03000 found in BRCHAR.
03100
03200
03300 0 >0 A break character was encountered. The break
03400 character is stored in BRCHAR (an INTEGER reference
03500 variable, see Open, 12-6) as a right-justified
03600 7-bit ASCII value. It may also be tacked on to the
03700 end of the result String or saved for next time,
03800 depending on the BREAKSET mode (see Breakset,
03900 12-22).
04000
04100
04200 12-42. If break table 0 is specified, the only criteria for
04300 termination are end of file or COUNT exhaustion. The routine is
04400 somewhat faster operating in this mode.
00100 SAILON NO. 57.2 SAIL 12-43
00200
00300
00400
00500 Scan ____
00600
00700
00800 Form:
00900
01000
01100 12-43. "RESULT" ← SCAN ( @"SOURCE" , BREAK_TABLE , @BRCHAR )
01200
01300
01400 Function:
01500
01600
01700 12-44. SCAN functions identically to INPUT with the following
01800 exceptions:
01900
02000
02100 1. The source is not a data file but the String SOURCE, called
02200 by reference. The String SOURCE is truncated from the left
02300 to produce the same effect as one would obtain if SOURCE were
02400 a data file. The disposition of the break character is the
02500 same as it is for INPUT.
02600
02700
02800 2. BRCHAR is directly specified as a parameter. INPUT gets its
02900 break character variable from a table set up by Open, 12-6.
03000
03100
03200 3. Line number considerations are irrelevant.
03300
03400
03500 Out ___
03600
03700
03800 Form:
03900
04000
04100 12-45. OUT(CHANNEL,"STRING")
04200
04300 Function:
04400
04500
04600 12-45. STRING is output to the file open on CHANNEL. If the
04700 device is a TTY, the String will be typed immediately. Buffered mode
04800 text output is employed for this operation. The data mode specified
04900 in the OPEN for this channel must be 0 or 1. The EOF variable will
05000 be set non-zero as described in Open, 12-6 if an error is detected
05100 and the program is enabled for it; 0 otherwise.
00100 SAILON NO. 57.2 SAIL 12-45
00200
00300
00400
00500 Linout ______
00600
00700
00800 Form:
00900
01000
01100 12-46. LINOUT ( CHANNEL , NUMBER );
01200
01300
01400 Function:
01500
01600
01700 12-47. ABS(NUMBER) mod 100,000 is converted to a 5 character ASCII
01800 string. These characters are placed in a single word in the output
01900 file designated by CHANNEL with the low-order bit (line-number bit)
02000 turned on. A tab is inserted after the line number. Mode 0 or 1
02100 must have been specified in the OPEN (Open, 12-6) for the results to
02200 be anywhere near satisfactory. EOF is set as in OUT.
02300
02400
02500 Wordin ______
02600
02700
02800 Form:
02900
03000
03100 12-48. VALUE ← WORDIN ( CHANNEL )
03200
03300
03400 Function:
03500
03600
03700 12-49. The next word from the file open on CHANNEL is returned. A
03800 0 is returned, and EOF (see Open, 12-6,Input, 12-40) set, when end of
03900 file or error is encountered. This operation is performed in
04000 buffered mode or dump mode, depending on the mode specification in
04100 the OPEN.
04200
04300
04400 Arryin ______
04500
04600
04700 Form:
04800
04900
05000 12-50. ARRYIN ( CHANNEL , @LOC , HOW_MANY );
00100 SAILON NO. 57.2 SAIL 12-50
00200
00300
00400
00500 Function:
00600
00700
00800 12-51. HOW_MANY words are read from the device and file open on
00900 CHANNEL, and deposited in memory starting at location LOC.
01000 Buffered-mode input is done if MODE (see Open, 12-6) is '10 or '14.
01100 Dump-mode input is done if MODE is '16 or '17. Other modes are
01200 illegal.
01300
01400
01500 12-52. If an end of file or enabled error condition occurs before
01600 HOW_MANY words are read, the EOF variable (see Open, 12-6) is set to
01700 the enabled bits in its left half, as usual. Its right half contains
01800 the number of words actually read. EOF will be 0 if the full request
01900 is satisfied.
02000
02100
02200 Wordout _______
02300
02400
02500 Form:
02600
02700
02800 12-53. WORDOUT ( CHANNEL , VALUE );
02900
03000
03100 Function:
03200
03300
03400 12-54. VALUE is placed in the output buffer for CHANNEL. An
03500 OUTPUT is done when the buffer is full or when a CLOSE or RELEASE is
03600 executed for this channel. Dump mode output will be done if dump
03700 mode is specified in the OPEN (see Open, 12-6). EOF is set as in
03800 OUT.
03900
04000
04100 Arryout _______
04200
04300
04400 Form:
04500
04600
04700 12-55. ARRYOUT ( CHANNEL , @LOC , HOW_MANY );
00100 SAILON NO. 57.2 SAIL 12-56
00200
00300
00400
00500 Function:
00600
00700
00800 12-56. HOW_MANY words are written from memory, starting at
00900 location LOC, onto the device and file open on channel CHANNEL. The
01000 valid modes are again '10, '14, '16, and '17. The EOF variable is
01100 set as in ARRYIN, except that the EOF bit itself will never occur.
01200
01300
01400 Mtape _____
01500
01600
01700 Form:
01800
01900
02000 12-57. MTAPE ( CHANNEL , MODE );
02100
02200
02300 Function:
02400
02500
02600 12-58. MTAPE is ignored unless the device associated with CHANNEL
02700 is a magnetic tape drive. It performs tape actions as follows:
02800
02900
03000 MODE FUNCTION
03100
03200 "A" Advance past one tape mark (or file)
03300 "B" Backspace past one tape mark
03400 "E" Write tape mark
03500 "F" Advance one record
03600 "R" Backspace one record
03700 "S" Write 3 inches of blank tape
03800 "T" Advance to logical end of tape
03900 "U" Rewind and unload
04000 "W" Rewind tape
04100
00100 SAILON NO. 57.2 SAIL 12-59
00200
00300
00400
00500 Useti, Useto ____________
00600
00700
00800 Form:
00900
01000
01100 12-59.
01200 USETI ( CHANNEL , VALUE );
01300 USETO (CHANNEL , VALUE );
01400
01500
01600 Function:
01700
01800
01900 12-60. The corresponding system function is carried out (see
02000 [Moorer] ).
02100
02200
02300 Realin, Intin _____________
02400
02500
02600 Form:
02700
02800
02900 12-61.
03000 VALUE ← REALIN ( CHANNEL );
03100 VALUE ← INTIN ( CHANNEL );
03200
03300
03400 Function:
03500
03600
03700 12-62. Number input may be obtained using the functions REALIN or
03800 INTIN, depending on whether a Real number or an Integer is required.
03900 Both functions use the same free field scanner, and take as argument
04000 a channel number.
04100
04200
04300 12-63. Free field scanning works as follows: characters are
04400 scanned one at a time from the input channel. Nulls, line
04500 numbers,and carriage returns are ignored. When a digit is scanned it
04600 is assumed that this is a number and the following syntax is used:
04700
04800 <number> ::= <sign><real number>
04900
05000 <real number> ::= <decimal number>|<decimal number><exponent>|
05100 <exponent>
00100 SAILON NO. 57.2 SAIL 12-63
00200
00300
00400
00500 <decimal number> ::= <integer>|<integer>.|<integer>.<integer>|
00600 .<integer>
00700
00800 <integer> ::= <digit>|<integer><digit>
00900
01000
01100 <exponent> ::= @<sign><integer>
01200
01300 <digit> ::= 0|1|2|3|4|5|6|7|8|9
01400
01500 <sign> ::= +|-|<empty>
01600
01700
01800
01900
02000 12-64. If the digit is not part of a number an error message will
02100 be printed and the program will halt. Typing a carriage return will
02200 cause the input function to return zero. On input, leading zeros are
02300 ignored. The ten most significant digits are used to form the
02400 number. A check for overflow and underflow is made and an error
02500 message printed if this occurs. When using INTIN any exponent is
02600 removed by scaling the Integer number. Rounding is used in this
02700 process. All numbers are accurate to one half of the least
02800 significant bit.
02900
03000
03100 12-65. After scanning the number the last delimiter is replaced on
03200 the input string and is returned as the break character for the
03300 channel. If no number is found, a zero is returned, and the break
03400 variable is set to -1; If an end of file or enabled error is sensed
03500 this is also returned in the appropriate channel variable. The
03600 maximum character count appearing in the OPEN call is ignored.
03700
03800
03900 Realscan, Intscan _________________
04000
04100
04200 Form:
04300
04400
04500 12-66.
04600 VALUE ← REALSCAN ( @"NUMBER_STRING" , @BRCHAR ) ; VALUE ← INTSCAN (
04700 @"NUMBER_STRING" , @BRCHAR );
00100 SAILON NO. 57.2 SAIL 12-67
00200
00300
00400
00500 Function:
00600
00700
00800 12-67. These functions are identical in function to REALIN and
00900 INTIN. Their inputs, however, are obtained from their NUMBER_STRING
01000 arguments. These routines replace NUMBER_STRING by a string
01100 containing all characters left over after the number has been removed
01200 from the front.
01300
01400
01500 Teletype I/O Functions ______________________
01600
01700
01800 Form:
01900
02000
02100 12-68.
02200 CHAR ← INCHRW;
02300 CHAR ← INCHRS;
02400 "STR" ← INCHWL;
02500 "STR" ← INCHSL ( @FLAG );
02600 "STR" ← INSTR ( BRCHAR );
02700 "STR" ← INSTRL ( BRCHAR );
02800 "STR" ← INSTRS ( @FLAG , BRCHAR );
02900 "STR" ← TTYIN ( TABLE , @BRCHAR );
03000
03100 "STR" ← TTYINL ( TABLE , @BRCHAR );
03200 "STR" ← TTYINS ( TABLE , @BRCHAR );
03300 OUTCHR ( CHAR );
03400 OUTSTR ( "STR" );
03500 CLRBUF;
03600 BACKUP;
03700 LODED ( "STR" );
00100 SAILON NO. 57.2 SAIL 12-69
00200
00300
00400
00500 Function:
00600
00700
00800 12-69. Each of the I/O functions uses the TTYUUO UUO's to do
00900 direct TTY I/O.
01000
01100 INCHRW waits for a character to be typed and returns that
01200 character.
01300
01400 INCHRS returns a negative value if no characters have been
01500 typed; otherwise it is INCHRW.
01600
01700 INCHWL waits for a line, terminated by a carriage-return and
01800 line feed (CR-LF) to be typed. It returns as a string
01900 all characters up to (not including) the CR. The LF is
02000 lost.
02100
02200 INCHSL returns NULL with FLAG ≠ 0 if no lines have been typed.
02300 Otherwise it sets FLAG to 0 and performs INCHWL.
02400
02500 INSTR returns as a string all characters up to, but not
02600 including, the first instance of BRCHAR. The BRCHAR
02700 instance is lost.
02800
02900 INSTRL waits for a line to be typed, then performs INSTR.
03000
03100 INSTRS is INCHSL if no lines are waiting; INSTRL otherwise.
03200
03300 TTYIN uses the break table features described in Breakset,
03400 12-22 and Input, 12-40 to return a string and break
03500 character. Mode "R" is illegal; line number modes are
03600 irrelevant. The input count (see Open, 12-6) is set at
03700 100.
03800
03900 TTYINL waits for a line to be typed, then does TTYIN.
04000
04100 TTYINS sets BRCHAR to ≠0 and returns NULL if no lines are
04200 waiting. Otherwise it is TTYINL.
00100 SAILON NO. 57.2 SAIL 12-69
00200
00300
00400 OUTCHR types its character argument (right-justified in an
00500 integer variable).
00600
00700 OUTSTR types its string argument.
00800
00900 CLRBUF flushes the input buffer.
01000
01100 BACKUP backs up the scan (when started by a system command).
01200
01300 LODED loads the line editor with the string argument.
01400
01500
01600 Pseudo-teletype functions (Stanford only) _________________________________________
01700
01800
01900 Form:
02000
02100
02200 12-70.
02300 line ← PTYGET ;
02400 PTYREL ( line );
02500 characteristics ← PTGETL ( line );
02600 PTSETL ( line , characteristics );
02700 number ← PTIFRE ( line );
02800 number ← PTOCNT ( line );
02900 char ← PTCHRW ( line );
03000 char ← PTCHRS ( line );
03100 PTOCHS ( line , char );
03200 PTOCHW ( line , char );
03300 PTOSTR ( line , "str" );
03400 string ← PTYALL ( line );
03500 string ← PTYSTR ( line , brchar );
03600 string ← PTYIN ( line, bktbl , @brchar );
00100 SAILON NO. 57.2 SAIL 12-71
00200
00300
00400
00500 Function:
00600
00700
00800 12-71.
00900
01000 PTYGET gets a new pseudo-teletype line number and returns it.
01100 The global variable .SKIP. is -1 if the attempt to get a
01200 PTY was successful, and 0 otherwise.
01300
01400 PTYREL releases PTY identified by "line".
01500
01600 PTGETL returns line characteristics for the PTY.
01700
01800 PTSETL sets line characteristics for thm PTY specified by
01900 "line".
02000
02100 PTIFRE returns the number of free characters in the PTY input
02200 buffer.
02300
02400 PTOCNT returns the number of free characters in the PTY output
02500 buffer.
02600
02700 PTCHRW waits for a character from the PTY and returns it.
02800
02900 PTCHRS reads a character from the PTY if there is one, returns
03000 -1 if none.
03100
03200 PTOCHS tries to send a character to a PTY. If the attempt was
03300 successful, the global variable .SKIP. is -1, otherwise
03400 0.
03500
03600 PTOCHW sends a character to a PTY, waiting if necessary.
03700
03800 PTOSTR sends the string to the PTY, waiting if necessary.
00100 SAILON NO. 57.2 SAIL 12-71
00200
00300
00400 PTYALL returns whatever is in the PTY's output buffer. No
00500 waiting is done.
00600
00700 PTYSTR reads characters from the PTY, waiting if necessary,
00800 until a character equal to "char" is seen. All but the
00900 break character is returned as the string. If the break
01000 character was '15 (carriage return), the following
01100 line-feed is snarfed.
01200
01300 PTYIN reads from the PTY (waiting if necessary) according to
01400 break table conventions. The break character is stored
01500 in "brchar".
01600
01700
01800
01900 STRING MANIPULATION ROUTINES
02000
02100
02200 Equ ___
02300
02400
02500 Form:
02600
02700
02800 12-73. VALUE ← EQU ( "STR1", "STR2" );
02900
03000
03100 Function:
03200
03300
03400 12-74. The value of this function is TRUE if STR1 and STR2 are
03500 equal in length and have identically the same characters in them (in
03600 the same order). The value of EQU is FALSE otherwise.
03700
03800
03900 TYPE CONVERSION ROUTINES
04000
04100
04200 Setformat _________
04300
04400
04500 Form:
04600
04700
04800 12-75. SETFORMAT ( WIDTH , DIGITS ) ;
00100 SAILON NO. 57.2 SAIL 12-76
00200
00300
00400
00500 Function:
00600
00700
00800 12-76. This function allows specification of a minimum width for
00900 strings created by the functions CVS, CVOS, CVE, CVF, and CVG (see
01000 Cvs, 12-80 and following). If this number (WIDTH) is positive,
01100 enough blanks will be inserted in front of the resultant string to
01200 make the entire results at least WIDTH characters long. The sign, if
01300 any, will appear after the blanks. If WIDTH is negative, leading
01400 zeroes will be used in place of blanks, The sign, of course, will
01500 appear before the zeroes. This parameter is initialized by the
01600 system to 0.
01700
01800
01900 12-77. In addition, the DIGITS parameter allows one to specify the
02000 number of digits to appear following the decimal point in strings
02100 created by CVE, CVF, and CVG. This number is initially 7. See the
02200 writeups on the functions Cve, Cvf, Cvg, 12-92 and following for
02300 details.
02400
02500
02600 Getformat _________
02700
02800
02900 Form:
03000
03100
03200 12-78. GETFORMAT ( @WIDTH , @DIGITS ) ;
03300
03400
03500 Function:
03600
03700
03800 12-79. The WIDTH and DIGIT settings specified in the last
03900 SETFORMAT call are returned in the appropriate reference parameters.
04000
04100
04200 Cvs ___
04300
04400
04500 Form:
04600
04700
04800 12-80. "ASCII_STRING" ← CVS ( VALUE );
00100 SAILON NO. 57.2 SAIL 12-81
00200
00300
00400
00500 Function:
00600
00700
00800 12-81. The decimal Integer representation of VALUE is produced as
00900 an ASCII String with leading zeroes omitted (unless WIDTH has been
01000 set by Setformat, 12-75 to some negative value). "-" will be
01100 concatenated to the String representing the decimal absolute value of
01200 VALUE if VALUE is negative.
01300
01400
01500 Cvos ____
01600
01700
01800 Form:
01900
02000
02100 12-82. "ASCII_STRING" ← CVOS ( VALUE );
02200
02300
02400 Function:
02500
02600
02700 12-83. The octal Integer representation of VALUE is produced as an
02800 ASCII String with leading zeroes omitted (unless WIDTH has been set
02900 to some negative value by Setformat, 12-75). No "-" will be used to
03000 indicate negative numbers. For instance, -5 will be represented as
03100 "777777777773".
03200
03300
03400 Cvis ____
03500
03600
03700 Form:
03800
03900
04000 12-84. "STRING" ← CVIS ( ITEM , @FLAG ) ;
04100
04200
04300 Function:
04400
04500
04600 12-85. The print name of ITEM is returned as a string. An Item's
04700 print name is the identifier used to declare it, or that provided by
04800 the NEW_PNAME function (see New_Pname, 12-88). FLAG is set to FALSE
04900 (0) if the appropriate string is found. Otherwise it is set to TRUE
05000 (-1), and you should not place great faith in the string result.
00100 SAILON NO. 57.2 SAIL 12-85
00200
00300
00400
00500 Cvsi ____
00600
00700
00800 Form:
00900
01000
01100 12-86. ITEM ← CVSI ( "PNAME" , @FLAG ) ;
01200
01300
01400 Function:
01500
01600
01700 12-87. The Item whose identifier (or name provided by New_Pname,
01800 12-88) is the same as the string argument PNAME is returned and FLAG
01900 set to FALSE if such an Item exists. Otherwise, something very
02000 random is returned, and FLAG is set to TRUE.
02100
02200
02300 New_Pname _________
02400
02500
02600 Form:
02700
02800
02900 12-88.
03000 NEW_PNAME (ITEM , "STRING" )
03100
03200
03300 Function:
03400
03500
03600 12-89. This function assigns to the Item the name "STRING". Don't
03700 perform this twice for the same Item without first deleting the
03800 previous one. The corresponding name or Item may be retrieved using
03900 CVIS or CVSI (above). You must use the REQUIRE n PNAMES construct in
04000 one of the files comprising your program for all this to work.
04100
04200
04300 Del_Pname _________
04400
04500
04600 Form:
04700
04800
04900 12-90.
05000 DEL_PNAME ( ITEM )
00100 SAILON NO. 57.2 SAIL 12-90
00200
00300
00400
00500 Function:
00600
00700
00800 12-91. This function deletes any string PNAME associated with this
00900 Item.
01000
01100
01200 Cve, Cvf, Cvg _____________
01300
01400
01500 Form:
01600
01700
01800 12-92.
01900 "STRING" ← CVE ( VALUE ); "STRING" ← CVF ( VALUE ); "STRING" ← CVG (
02000 VALUE );
02100
02200
02300 Function:
02400
02500
02600 12-93. Real number output is facilitated by means of one of three
02700 functions CVE,CVG, or CVF, corresponding to the E,G, and F formats of
02800 FORTRAN IV. Each of these functions takes as argument a real number
02900 and returns a string. The format of the string is controlled by
03000 another function SETFORMAT ( WIDTH,DIGITS) (see Setformat, 12-75)
03100 which is used to change WIDTH from zero and DIGITS from 7, their
03200 initial values. WIDTH specifies the minimum string length. If WIDTH
03300 is positive leading blanks will be inserted and if negative leading
03400 zeros will be inserted.
03500
03600
03700 12-94. The following table indicates the strings returned for some
03800 typical numbers. _ indicates a space and it is assumed that WIDTH←10
03900 and DIGITS←3.
04000
04100 CVF CVE CVG
04200 ______.000 __.100@-3_ __.100@-3_
04300 ______.001 __.100@-2_ __.100@-2_
04400 ______.010 __.100@-1_ __.100@-1_
04500 ______.100 __.100____ __.100____
04600 _____1.000 __.100@1__ __1.00____
04700 ____10.000 __.100@2__ __10.0____
04800 ___100.000 __.100@3__ __100.____
04900 __1000.000 __.100@4__ __.100@4__
00100 SAILON NO. 57.2 SAIL 12-94
00200
00300
00400 _10000.000 __.100@5__ __.100@5__
00500 _100000.000 __.100@6__ __.100@6__
00600 _1000000.000 __.100@7__ __.100@7__
00700 -1000000.000 _-.100@7__ _-.100@7__
00800
00900
01000
01100 12-95. The first character ahead of the number is either a blank
01200 or a minus sign. With WIDTH←-10 plus and minus 1 would print as:
01300
01400 CVF CVE CVG
01500 _00001.000 _0.100@1__ _01.00____
01600 -00001.000 -0.100@1__ -01.00____
01700
01800
01900
02000 12-96. All numbers are accurate to one unit in the eighth digit.
02100 If DIGITS is greater than 8, trailing zeros are included; if less
02200 than eight, the number is rounded.
02300
02400
02500 Cvstr _____
02600
02700
02800 Form:
02900
03000
03100 12-97. "STRING" ← CVSTR ( VALUE ) ;
03200
03300
03400 Function:
03500
03600
03700 12-98. VALUE is treated as a 5-character left-justified word full
03800 of ASCII. the result is a 5-character long String containing these
03900 characters. The low order bit of VALUE is ignored.
04000
04100
04200 Cvxstr ______
04300
04400
04500 Form:
04600
04700
04800 12-99. "STRING" ← CVXSTR ( VALUE ) ;
00100 SAILON NO. 57.2 SAIL 12-100
00200
00300
00400
00500 Function:
00600
00700
00800 12-100. VALUE is treated as a 6-character left-justified word full
00900 of SIXBIT. The result is a 6-character long String containing these
01000 characters, converted to ASCII.
01100
01200
01300 Cvd ___
01400
01500
01600 Form:
01700
01800
01900 12-101. VALUE ← CVD ( "ASCII_STRING" );
02000
02100
02200 Function:
02300
02400
02500 12-102. ASCII_STRING should be a String of decimal ASCII
02600 characters perhaps preceded by plus and/or minus signs. Characters
02700 with ASCII values ≤ SPACE ('40) are ignored preceding the number.
02800 Any character not a digit will terminate the conversion (with no
02900 error indication). The result is the internal (signed) 36-bit binary
03000 representation of the number.
03100
03200
03300 Cvo ___
03400
03500
03600 Form:
03700
03800
03900 12-103. VALUE ← CVO ( "ASCII_STRING" );
04000
04100
04200 Function:
04300
04400
04500 12-104. This function is the same as CVD except that the input
04600 characters are deemed to represent Octal values.
00100 SAILON NO. 57.2 SAIL 12-104
00200
00300
00400
00500 Cvasc _____
00600
00700
00800 Form:
00900
01000
01100 12-105. VALUE ← CVASC ( "STRING" );
01200
01300
01400 Function:
01500
01600
01700 12-106. This is the inverse function for CVSTR. Up to five ASCII
01800 characters will be fetched from the beginning of STRING and placed
01900 left-justified in VALUE. If the String is less than five characters
02000 long, the right characters will be padded with null (0) characters.
02100
02200
02300 Cvsix _____
02400
02500
02600 Form:
02700
02800
02900 12-107. VALUE ← CVSIX ( "STRING" );
03000
03100
03200 Function:
03300
03400
03500 12-108. The inverse for CVXSTR, this function works the same as
03600 CVASC except that up to six SIXBIT characters are placed in VALUE.
03700 The characters from STRING are converted from ASCII to SIXBIT before
03800 depositing them in VALUE.
03900
04000
04100 Cvfil _____
04200
04300
04400 Form:
04500
04600
04700 12-109. VALUE ← CVFIL ( "FILE_SPEC" , @EXTEN , @PPN ) ;
00100 SAILON NO. 57.2 SAIL 12-110
00200
00300
00400
00500 Function:
00600
00700
00800 12-110. FILE_SPEC has the same form as a file name specification
00900 for LOOKUP or ENTER. The SIXBIT for the file name is returned in
01000 VALUE. SIXBIT values for the extension and project-programmer
01100 numbers are returned in the respective reference parameters. Any
01200 unspecified portions of the FILE_SPEC will result in zero values.
01300 The global variable _SKIP_ (accessed by declaring it as EXTERNAL
01400 INTEGER _SKIP_) will be 0 if no errors occurred, ≠0 if an invalid
01500 file name specification is presented.
01600
01700 Arrinfo
01800
01900
02000 Form:
02100
02200
02300 12-110. VALUE ← ARRINFO ( ARRAY , PARAMETER );
02400
02500
02600 Function:
02700
02800
02900 12-111.
03000
03100 ARRINFO(ARRAY,-1) returns the number of dimensions for the array.
03200 This number is negative for String arrays.
03300
03400 ARRINFO(ARRAY,0) returns the total size of the array in words.
03500
03600 ARRINFO(ARRAY,1) returns the lower bound for the first
03700 dimension.
03800
03900 ARRINFO(ARRAY,2) returns the upper bound for the first
04000 dimension.
04100
04200 ARRINFO(ARRAY,3) returns the lower bound for the second
04300 dimension.
04400
04500 ARRINFO( ...) etc.
00100 SAILON NO. 57.2 SAIL 12-112
00200
00300
00400
00500 Arrblt ______
00600
00700
00800 Form:
00900
01000
01100 12-112. ARRBLT ( @LOC1 , @LOC2 , NUM );
01200
01300
01400 Function:
01500
01600
01700 12-113. NUM words are transferred from consecutive locations
01800 starting at LOC2 to consecutive locations starting at LOC1. No
01900 bounds checking is performed. This function does not work well for
02000 String Arrays.
02100
02200
02300 Arrtran _______
02400
02500
02600 Form:
02700
02800
02900 12-114. ARRTRAN ( ARRAY1, ARRAY2 );
03000
03100
03200 Function:
03300
03400
03500 12-115. This function copies information from ARRAY2 to ARRAY1.
03600 The transfer starts at the first data word of each array. The
03700 minimum of the sizes of ARRAY1 and ARRAY2 is the number of words
03800 transferred.
03900
04000
04100 LIBERATION-FROM-SAIL ROUTINES
04200
04300
04400 Code ____
04500
04600
04700 Form:
04800
04900
05000 12-116. RESULT ← CODE ( INSTR , @ADDR )
00100 SAILON NO. 57.2 SAIL 12-116
00200
00300
00400
00500 Function:
00600
00700
00800 12-117. This function is equivalent to the FAIL statements:
00900
01000
01100 EXTERNAL .SKIP. ;DECLARE AS _SKIP_ IN SAIL
01200 SETOM .SKIP. ;ASSUME SKIP
01300 MOVE 0,INSTR
01400 ADDI 0,@ADDR
01500 XCT 0
01600 SETZM .SKIP. ;DIDN'T SKIP
01700 RETURN (1)
01800
01900
02000 In other words, it executes the instruction formed by adding the
02100 address of the ADDR variable (passed by reference) to the number
02200 INSTR. Before the operation is carried out, AC1 is loaded from a
02300 special cell (initially 0). AC1 is returned as the result, and also
02400 stored back into the special cell after the instruction is executed.
02500 The global variable _SKIP_ (.SKIP. in DDT or FAIL) is FALSE (0)
02600 after the call if the executed instruction did not skip; TRUE
02700 (currently -1) if it did. Declare this variable as
02800 EXTERNAL INTEGER _SKIP_ if you want to use it.
02900
03000
03100 Call ____
03200
03300
03400 Form:
03500
03600
03700 12-118. RESULT ← CALL ( VALUE , "FUNCTION" );
00100 SAILON NO. 57.2 SAIL 12-119
00200
00300
00400
00500 Function:
00600
00700
00800 12-119. This function is equivalent to the FAIL statements:
00900
01000
01100 EXTERNAL .SKIP.
01200 SETOM .SKIP.
01300 MOVE 1,VALUE
01400 CALL 1,[SIXBIT /FUNCTION/]
01500 SETZM .SKIP. ;DID NOT SKIP
01600 RETURN (REGISTER 1)
01700
01800 The .SKIP. variable (_SKIP_ in SAIL) is set as described in the
01900 previous paragraph (CODE).
02000
02100
02200 Usercon _______
02300
02400
02500 Form:
02600
02700
02800 12-120.
02900 USERCON ( @INDEX , @VALUE , FLAG )
03000
03100
03200 Function:
03300
03400
03500 12-121. This function allows inspection and alteration of the
03600 "User Table" (see User Table, 17-1). Declare an index you are
03700 interested in as an External Integer (e.g., EXTERNAL INTEGER REMCHR).
03800 This will, when loaded, give an address which is secretly a small
03900 Integer index into the User Table. When passed by reference, this
04000 index is available to USERCON. The names and meanings of the various
04100 User Table indices can be found in the file HEAD, wherever SAIL
04200 compiler program text files are sold.
04300
04400
04500 12-122. USERCON always returns the current value of the
04600 appropriate User Table entry (the Global Upper Segment Table is used
04700 if FLAG is negative and your system knows about such things). If
04800 FLAG is odd, the contents of VALUE before the call replaces the old
04900 value in the selected entry of the selected table.
00100 SAILON NO. 57.2 SAIL 12-123
00200
00300
00400
00500 12-123. By now the incredible danger of this feature must be
00600 apparent to you. Be sure you understand the ramifications of any
00700 changes you make to any User Table value.
00800
00900
01000 Usererr _______
01100
01200
01300 Form:
01400
01500
01600 12-124. USERERR ( VALUE , CODE , "MSG" );
01700
01800
01900 Function
02000
02100
02200 12-125. MSG is printed on the teletype. If CODE = 2, VALUE is
02300 printed in decimal on the same line. Then on the next line the
02400 "LAST SAIL CALL" message is typed which indicates where in the user
02500 program the error occurred. A "?" or "→" character is typed and the
02600 user may type a standard reply (see ERROR MESSAGES, 14-19). If CODE
02700 is 1 or 2, a "→" will be typed and execution will be allowed to
02800 continue. If it is 0, a "?" is typed, and no continuation will be
02900 permitted.
03000
03100
03200 Point _____
03300
03400
03500 Form:
03600
03700
03800 12-126. VALUE ← POINT ( BYTE SIZE , @EFFECTIVE ADDRESS , LAST BIT
03900 NUMBER )
04000
04100
04200 Function:
04300
04400
04500 12-127. POINT returns a byte pointer (hence it is of type
04600 integer). The three arguments are enough to specify the three fields
04700 of a PDP-10 If the LAST BIT NUMBER is -1, POINT creates a byte
04800 pointer which, when used with an ILDB, will pick up the first byte
04900 from the word at EFFECTIVE ADDRESS. Otherwise, the three arguments
05000 to POINT are exactly analogous to the three arguments to POINT in
05100 FAIL.
00100 SAILON NO. 57.2 SAIL 13-1
00200
00300 SECTION 13
00400
00500 USE OF DEFINE
00600
00700 The SAIL DEFINE feature provides a limited macro capability with
00800 parameter substitution. The formal syntax for DEFINE declarations is
00900 given in DECLARATIONS, 3-1. Use of these macros is described below.
01000
01100
01200 Defining Macros
01300
01400
01500 13-1. When a macro of the form
01600
01700 DEFINE MAC(X,Y) = "FOR Y←1 STEP 1 UNTIL X DO"
01800
01900 is seen by the compiler (either at declaration level or statement
02000 level), it first associates with the "formal parameters" sequential
02100 indices (X=1, Y=2). Then it reads the String constant representing
02200 the macro body into String space, substituting for each occurrence of
02300 a formal parameter the character '177 followed by the character
02400 representing the index of this formal parameter. These special
02500 characters will be used to locate the actual parameters when the
02600 macro is expanded. The modified macro body is stored under the name
02700 of the macro, where it lies dormant until someone mentions it again.
02800
02900
03000 13-2. In what follows, the character ¬ will represent the
03100 character ('177) used to identify parameter locations. The number
03200 following it will always be the parameter index. The above macro is
03300 stored as:
03400
03500 FOR ¬2←1 STEP 1 UNTIL ¬1 DO
03600
03700
03800
03900 13-3. A macro may be re-defined (at statement level) as many times
04000 as desired. The new macro body replaces the old one. Macro names
04100 follow block structure, so for a macro with the same name as some
04200 other macro to be a redefinition, it must appear at the same block
04300 level as that other definition.
00100 SAILON NO. 57.2 SAIL 13-4
00200
00300
00400
00500 String Constants in Macro Bodies
00600
00700
00800 13-4. String constants may be represented in macro bodies, but two
00900 quote characters (") must be inserted for each one which would be
01000 necessary if the String constant appeared outside the macro body
01100 (which after all is itself a String constant, hence the problem).
01200
01300
01400 Using Macros
01500
01600
01700 13-5. When a macro name (ignore for the moment the possibility of
01800 parameters) is detected in a file, the body of that macro is
01900 retrieved and becomes the input to the SAIL scanner until the String
02000 is exhausted; the scanner then returns to the source file for its
02100 input. The macro name itself never makes it out of the scanner. If,
02200 while a macro body is providing input, another macro name is
02300 encountered, the original macro body is put aside until this new
02400 macro is exhausted. Nesting may occur to any level; however, it will
02500 be necessary to increase the size of the compiler's DEFINE push down
02600 stack if nesting gets extremely deep ( see the D switch in Switches,
02700 14-13).
02800
02900
03000 Macro Parameters
03100
03200
03300 13-6. If a macro body has been defined with formal parameters, the
03400 compiler will look for actual parameters to satisfy them when a macro
03500 is expanded. Actual parameters follow the macro name, are surrounded
03600 by parentheses and separated by commas.
00100 SAILON NO. 57.2 SAIL 13-7
00200
00300
00400
00500 13-7. A macro parameter is scanned as a String constant. However,
00600 for convenience, the following special rules apply to the scanning of
00700 a macro actual parameter:
00800
00900
01000 1) All blank characters after the left parenthesis are ignored.
01100
01200 2) If the first non-blank character is not the " character, the
01300 parameter String will be terminated by a comma or a right
01400 parenthesis, which will not appear in the parameter. If the
01500 " character is subsequently found, it is treated as any
01600 other text character.
01700
01800 3) If the first non-blank character is the " character, the
01900 parameter is scanned using the normal rules for String
02000 constants.
02100
02200
02300 Example
02400
02500
02600 13-8.
02700
02800 MAC("I","J") is equivalent to MAC(I,J);
02900 MAC("J+3" , "X&""A STRING""")
03000 is equivalent to MAC(J+3,X&"A STRING");
03100
03200 but MAC("""A STRING""","PROC(I,J)")
03300
03400 may not be abbreviated, because the meaning of the " character would
03500 otherwise be ambiguous in the first argument, and the commas and
03600 parentheses need protection in the second.
03700
03800
03900 Actual Parameter Expansion
04000
04100
04200 13-9. The actual parameter strings are stored in an ordered list
04300 just before the input stream is switched to the macro body. When one
04400 of the ¬number pairs appears, the input stream is switched to the
04500 (number)th actual parameter. Other macros (with or without
04600 parameters) may appear in these actual parameters without confusing
04700 the scanner (sic).
00100 SAILON NO. 57.2 SAIL 13-10
00200
00300
00400
00500 13-10. For an actual parameter to be recognized eventually as a
00600 String constant, enough " characters must surround it to allow one to
00700 survive on each end when it passes through the scanner for the last
00800 time. To be sure, the implementation of this feature is so wondrous
00900 that even the authors must resort to trial and error methods when
01000 complicated things are done\enod\attempted.
01100
01200
01300 Examples
01400
01500
01600 13-11.
01700
01800
01900 DEFINE TTY="1", SRC="2", BRK_ON_LFD="2";
02000 Comment for constant parameters for which
02100 it is desirable to include symbolic names,
02200 this is more efficient than assigning the
02300 parameter values to variables;
02400
02500 DEFINE TYPE(MSG)= "OUT(TTY,MSG)";
02600 Comment note inclusion of TTY macro in the
02700 body of the TYPE macro;
02800
02900 DEFINE TYPEC(MSG)="OUT(TTY,""MSG"")";
03000 Comment argument always to be made into
03100 a String constant;
03200
03300 DEFINE DEBUGGING = "TRUE", INP1(VBL,WHERE)=
03400 "BEGIN
03500 VBL←INPUT(SRC,BREAK_ON_LFD);
03600 IF DEBUGGING THEN
03700 TYPE(""""""INPUT TO VBL AT WHERE IS""""&VBL"");
03800 END"; Comment (probably);
03900
04000
04100 Using these definitions,
04200
04300 INP1(STR,INITIAL READ) expands to:
04400
04500 BEGIN
04600 STR←INPUT(2,2);
04700 IF TRUE THEN
04800 OUT(1,"INPUT TO STR AT INITIAL READ IS "&STR);
04900 END;
05000
05100
00100 SAILON NO. 57.2 SAIL 14-1
00200
00300 SECTION 14
00400
00500 COMPILER OPERATION
00600
00700
00800
00900 COMMAND FORMAT
01000
01100 Syntax
01200
01300
01400 14-1.
01500
01600 <command_line> ::= <binary_name> <listing_name> ←
01700 <source_list>
01800 ::= <file_spec> @
01900 ::= <file_spec> EXC
02000
02100 <binary_name> ::= <file_spec>
02200 ::= <empty>
02300
02400 <listing_name> ::= , <file_spec>
02500 ::= <empty>
02600
02700 <source_list> ::= <file_spec>
02800 ::= <source_list> , <file_spec>
02900
03000 <file_spec> ::= <file_name> <file_ext> <proj_prog>
03100 ::= <device_name> <file_spec> <switches>
03200 ::= <device_name> <switches>
03300
03400 <file_name> ::= <legal_sixbit_id>
03500
03600 <file_ext> ::= . <legal_sixbit_id>
03700 ::= <empty>
03800
03900 <proj_prog> ::= [ <legal_sixbit_id> , <legal_sixbit_id> ]
04000 ::= <empty>
04100
04200 <device_name> ::= <legal_sixbit_id>
04300
04400 <switches> ::= ( <unslashed_switch_list> )
04500 ::= <slashed_switch_list>
04600 ::= <empty>
04700
04800 <unslashed_switch_list> ::= <switch_spec>
04900 ::= <unslashed_switch_list> <switch_spec>
00100 SAILON NO. 57.2 SAIL 14-1
00200
00300
00400 <slashed_switch_list> ::= / <switch_spec>
00500 ::= <slashed_switch_list> / <switch_spec>
00600
00700 <switch_spec> ::= <valid_switch_name>
00800 ::= <signed_integer> <valid_switch_name>
00900
01000 <valid_switch_name> ::= D
01100 ::= L
01200 ::= M
01300 ::= P
01400 ::= Q
01500 ::= R
01600 ::= S
01700 ::= C
01800 ::= F
01900
02000
02100
02200 Semantics
02300
02400
02500 14-2. All this is by way of saying that SAIL accepts commands in
02600 essentially the same format accepted by DEC processors such as MACRO
02700 and FORTRAN. The binary file name is the name of the output device
02800 and file on which the ready to load object program will be written.
02900 The listing file, if included, will contain a copy of the source
03000 files with a header at the top of each page and an octal program
03100 counter entry at the head of each line (see Listing Features, 14-13).
03200 The listing file name is often omitted (no listing created). The
03300 source file list specifies a set of user-prepared files which, when
03400 concatenated, form a valid SAIL program (one outer block).
03500
03600
03700 14-3. legal_sixbit_identifier is a name which is acceptable to the
03800 time sharing system as a valid file name, device name, extension,
03900 etc. when its first six (device, file) or three (extension,
04000 project-programmer number) are converted from ASCII to SIXBIT. For
04100 more information about file and device names, see [Moorer].
04200
04300
04400 14-4. If file_ext is omitted from the binary_name, the extension
04500 for the output file will be .REL. The default extension for the
04600 listing file is .LST. SAIL will first try to find source files under
04700 the names given. If this fails, and the extension is omitted, the
04800 same file with a .SAI extension will be tried.
00100 SAILON NO. 57.2 SAIL 14-5
00200
00300
00400
00500 14-5. If device_name is omitted, DSK: is assumed. If proj_prog is
00600 omitted, the project-programmer number for the job is assumed.
00700
00800
00900 14-6. Switches are parameters which affect the operation of the
01000 compiler. A list of switches may appear after any file name. The
01100 parameters specified are changed immediately after the file name
01200 associated with them is processed. The meanings of the switches are
01300 given below.
01400
01500
01600 14-7. The binary, listing and (first) source file names are
01700 processed before compilation -- subsequent source names (and their
01800 switches) are processed whenever an end-of-file condition is detected
01900 in the current source file. Source files which appear after the one
02000 containing the outer block's END delimiter are ignored.
02100
02200
02300 14-8. Each new line in the command file (or entered from the
02400 teletype) specifies a separate program compilation. Any number of
02500 programs can be compiled by the same SAIL core image.
02600
02700
02800 14-9. The file_spec@ command causes the compiler to open the
02900 specified file as the command file. Subsequent commands will come
03000 from this file. If any of these commands is file_spec@, another
03100 switch will occur.
03200
03300
03400 14-10. The file_spec! command will cause the specified file to be
03500 run as the next processor. This program will be started in "RPG
03600 mode". That is, it will look on the disk for its commands if its
03700 standard command file is there -- otherwise, command control will
03800 revert to the TTY. The default option for this file name is .DMP.
03900 The default device is SYS.
04000
04100
04200 14-11. For information about logging in, running jobs, and so on,
04300 see [Moorer].
00100 SAILON NO. 57.2 SAIL 14-12
00200
00300
00400
00500 Rpg Mode
00600
00700
00800 14-12. The COMPILE, DEBUG, LOAD, and EXECUTE set of system
00900 commands may be used to compile and run SAIL programs. See [Moorer]
01000 for details. A typical command String to the system (which will
01100 prepare commands of the form described above and pass them to SAIL
01200 (after starting it) might be:
01300
01400 DEBUG /SAIL RECOG(-2L5MRR)=BEG+PROCS+RECOG/LIST,CMDSCN[1,DCS]
01500
01600 This command will cause the following commands to be placed in a file
01700 on your area by the name of QQSAIL.RPG:
01800
01900 RECOG.REL,RECOG.LST(-2L5MRR)←BEG,PROCS,RECOG
02000 CMDSCN.REL←CMDSCN[1,DCS]
02100 LOADER!
02200
02300 The /SAIL entry may be omitted if all files have a .SAI extension.
02400 The loader will load the files with DDT or RAID and then start the
02500 specified debugging program.
00100 SAILON NO. 57.2 SAIL 14-13
00200
00300
00400
00500 Switches
00600
00700
00800 14-13. The following table describes the SAIL parameter switches.
00900 If the switch letter is preceded in the table by the D character, a
01000 decimal number is expected as an argument. 0 is the default value.
01100 The character O indicates that an octal number is expected for this
01200 switch. Otherwise the argument is ignored.
01300
01400 ARG SWITCH FUNCTION
01500
01600 C This switch turns on CREFfing. The listing file (which
01700 must exist) will be in a format suitable for processing
01800 by CREF, the program which will generate a
01900 cross-reference listing of your SAIL program.
02000
02100 D For every occurrence of this switch in the command
02200 line, the amount of space for the push down stack used
02300 in expanding macros (see USE OF DEFINE, 13-0) is
02400 doubled. Use this switch if the compiler indicates to
02500 you that this stack has overflowed. This shouldn't
02600 happen unless you nest DEFINE calls extremely deeply.
02700 The compiler is initialized with /6f (i.e. list line
02800 numbers and macro names).
02900
03000 O F O is an octal number which specifies exactly what kind
03100 of listing format is generated. O contains information
03200 about 5 separate listing features, each of which is
03300 assigned a bit in O.
03400
03500 1 List the program counter (see / L switch below).
03600 2 List with line numbers from the source text.
03700 4 List the macro names before expansion.
03800 10 Expand macro texts in the listing file.
03900 20 Surround each listed macro expansion with ⊂ and ⊃ .
04000
04100 O L In compiling a SAIL program, an internal variable
04200 called PCNT (for program counter) is incremented (by
04300 one) for each word of code generated. This value,
04400 initially 0, represents the address of a word of code
04500 in the running program, relative to the load point for
04600 this program. The current octal value of PCNT plus the
04700 value of another internal variable called LSTOFFSET, is
04800 printed at the beginning of each output line in a
04900 listing file. For the first program compiled by a
05000 given SAIL core image, LSTOFFSET is initially 0. If
05100 the L switch occurs in the command and the value O is
00100 SAILON NO. 57.2 SAIL 14-13
00200
00300 non-negative, O replaces the current value of
00400 LSTOFFSET. If O is -1, the current size of DDT is put
00500 into LSTOFFSET. If O is -2, the current size of RAID
00600 is used. In "RPG mode" the final value of PCNT is
00700 added to LSTOFFSET after each compilation. Thus by
00800 deleting all .REL files produced by SAIL, and by
00900 compiling all SAIL programs which are to be loaded
01000 together with one RPG command which includes the L
01100 switch, you can obtain listing files such that each of
01200 these octal numbers represents the actual starting core
01300 address of the code produced by the line it precedes.
01400 At the time of this writing, RPG would not accept minus
01500 signs in switches to be sent to processors. Keep
01600 trying.
01700
01800 D M D is a number from 1 to 6. This parameter puts the
01900 compiler in one of several debugging modes. This
02000 switch is most useful to compiler fixers, but some of
02100 the modes are of general interest. The functions
02200 represented by each of these modes are described in
02300 Debugging modes, 14-14 below.
02400
02500 P Each occurrence of this switch doubles the size of the
02600 system push down list. It has never been known to
02700 overflow.
02800
02900 Q Each occurrence doubles the size of the String push
03000 down list. No trouble has been encountered here,
03100 either.
03200
03300 R Each occurrence doubles the size of the compiler's
03400 parsing and semantic stacks. A long conditional
03500 statement of the form (IF ... THEN ... ELSE IF ...
03600 THEN ... ELSE IF ... ) has been known to cause these
03700 stacks to overflow their normally allocated sizes.
03800
03900 D S The size of String space is Set to D words. String
04000 space usage is a function of the number of identifiers,
04100 especially macros, declared by the user. In the rare
04200 case of String space exhaustion, 5000 is a good first
04300 number to try.
00100 SAILON NO. 57.2 SAIL 14-14
00200
00300
00400
00500 Debugging modes
00600
00700
00800 14-14. Certain versions of the SAIL compiler have a debugging
00900 facility built into the inner loop of the parser. It is willing to
01000 display information about the current state of the compilation at
01100 strategic times. This routine can be in one of several modes. A
01200 debugging mode is initially specified using the M switch described
01300 above. It can be changed by the user as the compilation progresses.
01400 The modes and their functions are as follows:
01500
01600 1) Just before each code-generator is called, its name is
01700 displayed on the TTY along with the top few elements of the
01800 parse and semantic stacks. If the TTY is a DPY, one also gets
01900 the current input line with an arrow underneath indicating the
02000 next element to be scanned. If you do not know what to look
02100 for in the stack, don't use this mode. Compilation may be
02200 continued by typing the character "P".
02300
02400 2) No information is displayed in this mode. However line breaks
02500 and asynchronous breaks (see below) can still occur.
02600
02700 3) Just before each parse production is compared to the parse
02800 stack, the name of the production and the other information
02900 mentioned above is presented. Proceed by typing "P".
03000 Compilation takes forever in this mode.
03100
03200 4) This mode does not cancel any of modes 1, 2,or 3. However, it
03300 puts the debugging routines in a mode wherein they will not
03400 wait for a user go-ahead before proceeding from the displays
03500 described for these modes. Line and asynchronous breaks are
03600 still enabled in this mode, and may be used to regain control
03700 of things.
03800
03900 5) This mode has no very useful application if the TTY is really a
04000 TTY. However if it is secretly a DPY, the current input line
04100 is continuously presented along with an arrow showing the
04200 compiler's progress through it. No user go-ahead is necessary
04300 after each presentation. All other modes are cancelled. Line
04400 and asynchronous breaks are enabled.
04500
04600 6) This is the default mode. No information is displayed. The
04700 debugging routines are completely detached from the compilation
04800 loop. Line and asynchronous breaks are disabled. The only way
04900 to get any of the information described above is to start over.
00100 SAILON NO. 57.2 SAIL 14-15
00200
00300
00400
00500 14-15. If you have the compiler in a position where it is willing
00600 to listen to a "P" to continue, you may also type some other things.
00700 The most interesting one is the "L" command. Typing "L" followed by
00800 a 5 character line number, a "/", and a decimal page number,
00900 terminated with a carriage return, causes the compiler to remember
01000 this page and line number, and to stop with a Line Break message and
01100 the information described above just after the specified line has
01200 been read. At this point you may change modes (see below) or not, as
01300 you prefer, and type "P" to continue. This command is really not too
01400 useful unless you are a compiler fixer.
01500
01600
01700 14-16. To change modes while compiling, type any number of
01800 parameter-M pairs to the debugging interpreter before typing "P" to
01900 go on.
02000
02100
02200 14-17. To get the compiler's attention when it is operating in
02300 one of the modes 2, 4, or 5, simply type a carriage return. Very
02400 shortly the compiler will display an Asynchronous Break message, the
02500 print line, and some stack elements. Then you may change modes, set
02600 a line break, or simply proceed. This is often useful simply to
02700 convince yourself that your program is still being compiled if you
02800 are running in mode 2. If you are operating in mode 6, the compiler
02900 will not listen to your plea. Start the compiler in mode 2 if you
03000 want this feature, but be warned that things will slow down
03100 considerably (10%?).
03200
03300
03400 14-18. Here is an example of a compile string which a user who
03500 just has to try every bell and whistle available to him might type to
03600 compile a file named NULL:
03700
03800
03900 COMPILE /LIST /SAIL NULL(RR-2L1M4M5000S)
04000
04100 The switch information contained in parentheses will be sent
04200 unchanged to SAIL. Note the convention which allows one set of
04300 parentheses enclosing a myriad of switches to replace a "/" character
04400 inserted before each one. This string tells the compiler to compile
04500 NULL using parse and semantic stacks four times larger than usual
04600 (RR). A listing file is to be made which assumes that RAID will be
04700 loaded and NULL will be loaded right after RAID (-2L). The user
04800 wants to see the stack and input line just before every code
04900 generating routine is called (1M), but he does not want the compiler
05000 to stop after each display (4M). His program is big enough to need
05100 5000 words of String space (5000S).
00100 SAILON NO. 57.2 SAIL 14-18
00200
00300
00400
00500 ERROR MESSAGES
00600
00700
00800 14-19. If the compiler detects a syntax or semantic error while
00900 compiling a program it will provide the user with the following
01000 information:
01100
01200 1) The error message. These are English phrases or sentences
01300 which attempt to diagnose the problem. If a message is
01400 vague it is because no specific test for the error has been
01500 made and a catchall routine detected it. If the message
01600 begins with the word "DRYROT" it means that there is a bug
01700 in the compiler which some strangeness in your program was
01800 able to tickle. See a system programmer about this.
01900
02000 2) The current input line. Page and line number, along with
02100 the text of the line being scanned, are typed. If the
02200 console device is a TTY, a line feed will occur at the point
02300 in the line just following the last program element scanned.
02400 If the device is a DPY, the line will be displayed with a
02500 vertical arrow below the scan position. The absence of a
02600 position indicator means that a macro (DEFINE) body is being
02700 expanded.
02800
02900 3) "CALLED FROM xxxxx". This is a message of value to compiler
03000 debuggers only.
03100
03200 4) A question mark or arrow (→ or ↑).
00100 SAILON NO. 57.2 SAIL 14-20
00200
00300
00400
00500 14-20. Respond to the prompt in any of the following ways:
00600
00700 CR Try to continue compilation. A message will be printed and
00800 the sequence reentered if recovery is impossible (if a "?"
00900 was typed instead of an arrow).
01000
01100 LF Continue and don't stop from now on. The program will not
01200 stop if it can help it. Messages will fly by (at an
01300 unreadable rate on DPYs) until the compilation is complete
01400 or an error occurs from which no recovery is possible. In
01500 the latter case the question sequence is reentered.
01600
01700 S Restart. Sometimes useful if you are debugging the compiler
01800 (or if you were compiling the wrong file). The program is
01900 restarted, accepting compilation commands from the TTY.
02000
02100 X Exit. All files are closed in their current state. The
02200 program exits to the system.
02300
02400 L Look at stack. This enters a part of the debugging routine
02500 (see Debugging modes, 14-14 above) to allow examination of
02600 the parse and semantic stacks. The compiler will lead you
02700 by the hand through these procedures.
02800
02900 E Edit. This command must be followed by a carriage return,
03000 or a space, a filename (in standard format, assumes DSK) and
03100 a carriage return. If the filename is missing, the SOS
03200 editor (see [Savitzky]) is started, given instructions to
03300 edit the current source file and to move the editing pointer
03400 to the current page and line number. If a file name is
03500 present, that file is edited starting at the beginning.
03600 This feature is available outside Stanford only if the SOS
03700 editor is available, and is modified to read a standard CCL
03800 file for its input.
03900
04000 D Enter DDT or RAID if one is loaded. Otherwise, type "NO
04100 DDT" and re-question.
04200
04300
04400 14-21. Any other character will cause the error routines to spew
04500 forth a summary of this table and re-enter the question sequence.
00100 SAILON NO. 57.2 SAIL 14-22
00200
00300
00400
00500 STORAGE ALLOCATION
00600
00700
00800 14-22. The compiler dynamically allocates working storage for its
00900 push down lists, symbol tables, string spaces, etc. It normally runs
01000 with a standard allocation adequate for most programs. Switch
01100 settings given above may be used to change these allocations. If
01200 desired, these allocations may also be changed by typing ↑C, followed
01300 by REE (reenter). The compiler will ask you if you want to allocate.
01400 Type Y to allocate, N to use the standard allocation, and any other
01500 character to use the standard allocations and print out what they
01600 are. All entries will be prompted. Numbers should be decimal.
01700 Typing alt-mode instead of CR will cause standard allocation to be
01800 used for the remaining values. The compiler will then start,
01900 awaiting command input from the teletype.
02000
02100
02200 14-23. For Stanford "Global Model" users, the REE command will
02300 also delete any REQUIREd or previously typed segment name
02400 information. The initialization sequence will then ask for new
02500 names.
00100 SAILON NO. 57.2 SAIL 15-1
00200
00300 SECTION 15
00400
00500 PROGRAM OPERATION
00600
00700
00800
00900 LOADING AND STARTING SAIL PROGRAMS
01000
01100 Loading
01200
01300
01400 15-1. Load the main program, any separately compiled procedure
01500 files (see Separately Compiled Procedures, 16-7), any assembly
01600 language (see PROCEDURE IMPLEMENTATION, 17-48) or Fortran procedures,
01700 and DDT or RAID if desired. This is all automatic if you use the
01800 LOAD or DEBUG or EXECUTE system commands (see [Moorer]). Any of the
01900 SAIL execution time routines requested by your program will be
02000 searched out and loaded automatically from SYS:LIBSAI.REL. If the
02100 shared segment (SYS:SAISEG, etc.) is available and desired, type /Y
02200 as as your very first LOADER command (before /D even). This is done
02300 automatically by RPG at Stanford.
02400
02500
02600 Starting the Program -- Normal Operation
02700
02800
02900 15-2. For most applications, SAIL programs can by started using
03000 the START, RUN, EXECUTE, or TRY system commands, or by using the $G
03100 command of DDT (RAID). The SAIL storage areas will be initialized.
03200 This means that all knowledge of I/O activity, associative data
03300 structures, strings, etc. from any previous activation of the
03400 program will be lost. All strings (except constants) will be cleared
03500 to NULL. All compiled-in arrays which were not PRELOADed will be
03600 cleared to 0, NULL, or PHI, whichever is appropriate. Then execution
03700 will begin with the first statement in the outer block of your main
03800 program. As each block is entered, its arrays will be cleared as
03900 they are allocated. Variables are not cleared. The program will
04000 exit when it leaves this outer block.
04100
04200
04300 Starting the Program in "RPG" Mode
04400
04500
04600 15-3. SAIL programs may be started at one of two consecutive
04700 locations: at the address contained in the cell JOBSA in the job data
04800 area, or at the address just following that one. The global variable
04900 RPGSW is set to 0 in the former case, -1 in the latter. Aside from
05000 this, there is no difference between the two methods. This cell may
05100 be examined by declaring RPGSW as an EXTERNAL INTEGER.
00100 SAILON NO. 57.2 SAIL 15-3
00200
00300
00400
00500 Starting the Program with Allocation Modifications
00600
00700
00800 15-4. If the default (or REQUIREd) storage allocations for such
00900 things as the push down stacks or string space are insufficient, the
01000 program may be started using the REENTER system command. You may
01100 then answer questions as described in STORAGE ALLOCATION, 14-22. You
01200 can find out what the standard allocations are by typing a space
01300 after the system types ALLOC? at you. Arrays, Leap spaces and I/O
01400 buffers are allocated dynamically, obtaining more storage from the
01500 operating system if necessary. See Storage Allocation Routines, 17-5
01600 and following for ways of cooperating with SAIL with respect to
01700 storage allocation if you write machine language subroutines.
01800
01900
02000 ERROR MESSAGES
02100
02200
02300 15-5. Error messages have nearly the same format as those from the
02400 compiler (ERROR MESSAGES, 14-19). They indicate that
02500
02600 1) an array subscript has overflowed;
02700
02800 2) a case index is out of range;
02900
03000 3) a stack has overflowed while allocating space for a
03100 recursive procedure; or
03200
03300 4) one of the execution time routines has detected an error.
03400
03500
03600 15-6. The "CALLED FROM" address identifies, in the first 3 cases,
03700 the location in the user program where the error occurred ; the "LAST
03800 SAIL CALL AT" address gives the location of the faulty call on the
03900 SAIL routine for type 4 messages.
04000
04100
04200 15-7. All the replies to error messages described in ERROR
04300 MESSAGES, 14-19 are valid except the "L" option. If no file name is
04400 typed with the "E" option, the editor re-opens the last file
04500 mentioned in the EDIT system command (if the appropriate version SOS
04600 is available.
04700
04800
04900 15-8. The function USERERR may be used to activate the SAIL error
05000 message mechanism. See Usererr, 12-124 for details.
00100 SAILON NO. 57.2 SAIL 15-8
00200
00300
00400
00500 DEBUGGING
00600
00700
00800 15-9. The code output for SAIL programs is designed to be fairly
00900 easy to understand when examined using the DDT debugging language or
01000 Stanford's display oriented RAID program. A knowledge of the
01100 debugger you have chosen is required before this section will be
01200 comprehensible.
01300
01400
01500 Symbols
01600
01700
01800 15-10. Only those symbols which have been declared INTERNAL (see
01900 Separately Compiled Procedures, 16-7) and those declared in the
02000 currently open "program" are available at a given time. The name of
02100 a SAIL program as far as DDT or RAID (henceforth DDRAID) is concerned
02200 is the name of the outer block of that program. If no name is given
02300 for this block, the name M. will be the default.
02400
02500
02600 15-11. Only the first six non-blank characters of a block name or
02700 identifier will be used in forming a DDRAID symbol. If two
02800 identifiers in the same block have the same first six characters the
02900 program using them will not get confused, but the user might when
03000 trying to locate these identifiers.
03100
03200
03300 15-12. To obtain symbols for the execution time routines, load
03400 RUNTIM.REL (available from your friendly local SAIL maintainer) with
03500 your other files. The routines will be loaded from this file, which
03600 includes symbols, instead of from the LIBSAI library or shared
03700 segment, which do not. Your program will be several thousand words
03800 longer when this file is used.
03900
04000
04100 Blocks
04200
04300
04400 15-13. All block names and identifiers used as variables,
04500 procedures or labels in a given (main or separate procedure) program
04600 are available for typeout when that program is "open" (NAME$: has been
04700 typed). To refer to a symbol, type BLOCK_NAME&SYMBOL/ (; for RAID).
04800 The block name may be omitted if you have "opened" the block with
04900 BLOCK_NAME$&. The symbol table is block-structured only to the
05000 extent that block names have appeared in the source program. For
05100 instance, in the program
00100 SAILON NO. 57.2 SAIL 15-13
00200
00300
00400
00500 BEGIN "NAME1"
00600 INTEGER I,J;
00700 ...
00800 BEGIN
00900 INTEGER I,K;
01000 ...
01100 END;
01200 ...
01300 END "NAME1"
01400
01500 the symbols J, K, and both symbols I are considered by DDRAID to
01600 belong in the same block. Therefore confusion can result with
01700 respect to I. This approach was taken to avoid the necessity of
01800 generating meaningless block names for DDRAID when none were given in
01900 the source program. A compound statement will be considered by
02000 DDRAID to be a block if it has a name.
02100
02200
02300 Sail-Generated Symbols
02400
02500
02600 15-14. Some extra symbols are generated by SAIL and will show up
02700 when you are using DDRAID. They are:
02800
02900 ACS The accumulators P (system push down list pointer), SP
03000 (string push down pointer), and TEMP (commonly used
03100 temporary) are given symbolic names. Currently P='17,
03200 SP='16, TEMP='14.
03300
03400 OPS The op codes for the UUOs ERR., ERROR., FIX, FLOAT, PDLOV,
03500 and ARERR (subscript overflow UUO) are included to make
03600 these easy to detect in the code.
03700
03800 ARRAYS For each array declared in the outer block (built-in
03900 arrays), the fixed address of its first element is given a
04000 symbolic name. This name is constructed from the
04100 characters of the array name (up to the first 5) followed
04200 by a period. For instance, the first element of array CHT
04300 is CHT.; the first element of PDQARR is PDQAR.; The last
04400 semicolon was really a period. This dotted symbol points
04500 to the second word of the first descriptor for String
04600 Arrays (see STRINGS, 17-15, ARRAY IMPLEMENTATION, 17-35).
00100 SAILON NO. 57.2 SAIL 15-14
00200
00300
00400 BLOCKS The first word of the first executable statement of every
00500 block or compound statement which has been given a name is
00600 given a label created in the same way as those for arrays
00700 above. This label cannot be gone to in the source
00800 program. It causes no program inefficiency. This label
00900 points at the first word of the compound tail -- not the
01000 first word of code generated for the block (skips any
01100 procedure or array declaration code).
01200
01300 START The first word of code generated for any given program is
01400 given the name "S.".
01500
01600
01700 Warnings
01800
01900
02000 Long Names
02100
02200
02300 15-16. Since only the first 6 characters of an identifier are
02400 available, it is wise to declare symbols which will be examined by
02500 DDRAID in such a way that these six characters will uniquely identify
02600 them.
00100 SAILON NO. 57.2 SAIL 16-1
00200
00300 SECTION 16
00400
00500 PROGRAM STRUCTURE
00600
00700
00800
00900 THE SAIL CORE IMAGE (REQUIRED)
01000
01100
01200 16-1. The following things must be present in a core image
01300 containing SAIL-compiled files:
01400
01500
01600 Main Program
01700
01800
01900 16-2. A SAIL "main program", or an assembly language program which
02000 looks an awful lot like a SAIL main program, must be present if any
02100 SAIL-compiled files are. A SAIL source program which has no
02200 entry-specification as its first element satisfies this requirement.
02300 The first statement executed after storage allocation is complete
02400 will be its first statement. There should be no more than one main
02500 program per core image.
02600
02700
02800 16-3. The salient characteristics of a main program are:
02900
03000 1) Its .REL file has a starting address block (the loader will
03100 tell the time sharing system to start the program at this
03200 address).
03300
03400 2) Its first task is to determine whether the program was
03500 started in RPG mode. If so, the global variable RPGSW is
03600 set to TRUE; otherwise FALSE.
03700
03800 3) Its next task is to call the storage allocator with
03900 JSR SAILOR.
04000
04100 4) It should then proceed with the main control of the program.
04200
04300 4) It should execute a POPJ 17,0 when it is all done.
04400
04500 5) It may not execute any UUOs except SAIL UUOs (nor alter
04600 permanently the UUO locations 40 and 41) without great
04700 caution.
00100 SAILON NO. 57.2 SAIL 16-4
00200
00300
00400
00500 Storage Allocation, Basic Utilities
00600
00700
00800 16-4. There is a set of routines which must always be loaded to
00900 establish the operating environment for SAIL programs. These
01000 routines allocate storage, set up push down pointers, and initialize
01100 some of SAIL's internal tables. Other routines included in this
01200 package are a String garbage collector (see STRINGS, 17-15) and
01300 several basic routines which many others call upon.
01400
01500
01600 16-5. These programs will be loaded automatically from LIBSAI.REL
01700 if the JSR SAILOR instruction, where SAILOR is an external request,
01800 is present in the main program (this is automatic for SAIL-compiled
01900 main programs). If the shared segment option is available, they may
02000 also be included by mentioning SYS:SAILOW (or /Y) as the very first
02100 thing in your LOADER input string (done automatically at Stanford.
02200
02300
02400 Other Execution-Time Routines
02500
02600
02700 16-6. All I/O, String-handling, etc. is done by routines which
02800 understand about SAIL. Programs requiring these services should
02900 probably use these routines. SAIL-compiled files automatically
03000 request these blessed routines from LIBSAI.REL, or link to the second
03100 segment versions via RPG at Stanford.
03200
03300
03400 OPTIONAL ADDITIONS
03500
03600 Separately Compiled Procedures
03700
03800
03900 16-7. When a program becomes extremely large it becomes useful to
04000 break the program up into several files which can be compiled
04100 separately. This can be done in SAIL by preparing one file as a main
04200 program, and one or more other files as programs each of which
04300 contains one or more procedures to be called by the main program.
04400 Such a file must have the following characteristics:
00100 SAILON NO. 57.2 SAIL 16-7
00200
00300
00400 1) An entry specification (see Entry Specifications, 2-1) must
00500 be the first item in the program (preceding even the BEGIN
00600 for its outer block). The list of identifiers will be used
00700 to form an Entry Block for the loader. Therefore the file
00800 may be placed in a user library if desired. The format of
00900 libraries is described in [Weiher]. The identifier(s)
01000 appearing in the entry list may be any valid identifiers,
01100 but usually they will be the names of the procedures
01200 contained in the file. No starting address will be issued
01300 for a program containing an Entry Specification. No
01400 checking is done to see if entry identifiers are ever really
01500 declared in the body of the program.
01600
01700 2) Since no starting address is present for this file, entry to
01800 code within it may only be to the procedures it contains;
01900 the statements in the outer block, if any, can never be
02000 executed. All procedures to be called from the main program
02100 (or procedures in other files) must be qualified with the
02200 INTERNAL attribute when they are declared. External
02300 procedure declarations with headings identical to those of
02400 the actual declarations must appear in all those programs
02500 which call these procedures.
02600
02700 3) These internal procedures must be uniquely identifiable by
02800 the first six characters of their identifiers. In general,
02900 any two internal procedure names (or any other Internal
03000 variables in the same core image) with the same first six
03100 characters will cause incorrect linkages when the programs
03200 are loaded.
03300
03400 4) Any variables (simple or array) which appear in the outer
03500 block of a Separately Compiled Procedure program will be
03600 global to the procedures in this program, but not available
03700 to the main program (unless they are connected by
03800 Internal/External declarations -- see below). Arithmetic
03900 arrays in these outer blocks will always be zero when the
04000 program is first loaded, but will never be cleared as others
04100 are (see Starting the Program -- Normal Operation, 15-2) --
04200 String arrays are always cleared.
04300
04400 5) Any variable, procedure or label may contain the attribute
04500 INTERNAL or EXTERNAL in its declaration (ITEMS may not).
00100 SAILON NO. 57.2 SAIL 16-8
00200
00300
00400
00500 16-8. The INTERNAL attribute does not affect the storage
00600 assignment of the entity it represents, nor does it have any effect
00700 on the behavior of the entity (or the scope of its identifier) in the
00800 file wherein it appears. However, its address and (the first six
00900 characters of) its name are made available to the loader for
01000 satisfying External requests.
01100
01200
01300 16-9. No space is ever allocated for an External declaration.
01400 Instead, a list of references to each External identifier is made by
01500 the compiler. This list is passed to the loader along with the first
01600 six characters of the identifier name. When an Internal name
01700 matching it is found during loading, its associated address is placed
01800 in each of the instructions mentioned on the list. No program
01900 inefficiency at all results from External/Internal linkages (belay
02000 that -- references to External arrays are sometimes more
02100 inefficient).
02200
02300
02400 16-10. The entity finally represented by an External identifier is
02500 only accessible within the scope of the External declaration.
02600 Transfers to external labels are always allowed, but if things work
02700 correctly when this is done it is only by sheer luck that they do.
02800
02900
03000 Fortran Procedures
03100
03200
03300 16-11. For a program written in DEC FORTRAN IV to run in the SAIL
03400 environment, the following restrictions must be observed:
03500
03600 1) It must be a SUBROUTINE or FUNCTION, not a main program.
03700
03800 2) It must not execute any FORTRAN I/O calls. The UUO
03900 structures of the two languages are not compatible.
04000
04100 3) It must be declared as a Fortran Procedure (see Fortran
04200 Procedures, 6-12) in the SAIL program which calls it.
04300
04400 The type bits required in the argument addresses for Fortran
04500 arguments are passed correctly to these routines.
04600
04700 The SAIL compiler will not produce a procedure to be called from
04800 FORTRAN.
00100 SAILON NO. 57.2 SAIL 16-12
00200
00300
00400
00500 Assembly Language Procedures
00600
00700
00800 16-12. The implementation section contains the following
00900 paragraphs to aid in writing assembly language procedures: User
01000 Table, 17-1, STRINGS, 17-15, ARRAY IMPLEMENTATION, 17-35, Storage
01100 Allocation Routines, 17-5, and PROCEDURE IMPLEMENTATION, 17-48. In
01200 addition, the following rules should be observed:
01300
01400 1) The ENTRY, INTERNAL, and EXTERNAL pseudo-ops should be used
01500 to obtain linkages for procedure names and "global"
01600 identifiers (remember that only six characters are used for
01700 these linkage names.
01800
01900 2) Accumulators P (currently '17) and SP ('16) should be
02000 preserved over function calls. P may be used as a push-down
02100 pointer for arithmetic values and return addresses. SP is
02200 the string stack pointer. String results are returned on
02300 this stack. Arithmetic results are returned in AC 1 (see
02400 PROCEDURE IMPLEMENTATION, 17-48).
02500
02600 3) The UUO locations 40 and 41 should be preserved.
02700
02800 4) JOBFF must be set by the user to some free buffer area
02900 before OUTBUF or INBUF UUOs are executed. JOBFF is
03000 periodically set by SAIL routines to an invalid address.
03100
03200 5) The CORE UUO may be used to increase memory size, but never
03300 to decrease it. Never attempt to use directly any of the
03400 memory space currently assigned to the job (except that
03500 explicitly provided in the routine). Release all memory
03600 obtained in this way before returning to SAIL routines. See
03700 Storage Allocation Routines, 17-5 for instructions on
03800 obtaining core from the SAIL memory allocators (a much
03900 safer, and sometimes faster way).
04000
04100
04200 Others
04300
04400
04500 16-13. There are no other known processors which will produce
04600 SAIL-compatible programs. In particular, the LISP 1.6 system, by its
04700 very nature, contains storage allocation conflicts which are
04800 difficult to resolve. If a great need for this kind of compatibility
04900 develops it can be provided.
00100 SAILON NO. 57.2 SAIL 17-1
00200
00300 SECTION 17
00400
00500 IMPLEMENTATION INFORMATION
00600
00700
00800
00900 STORAGE LAYOUT
01000
01100 User Table
01200
01300
01400 17-1. All working storage areas for a SAIL-generated program and
01500 its execution-time routines are dynamically allocated -- some just
01600 once when the program is first started, some as more space is needed.
01700
01800
01900 17-2. The first area allocated is a several hundred word table
02000 which contains information about the remaining storage areas and
02100 global variables for the execution-time routines. A single internal
02200 variable, GOGTAB, will always contain a pointer to this table. The
02300 execution-time routines make all accesses to storage through this
02400 table or through user-supplied addresses. They would therefore be
02500 totally re-entrant if the GOGTAB variable were allowed to vary over
02600 several users.
02700
02800
02900 17-3. A FAIL source file containing symbolic indices for the user
03000 table, as well as some useful MACROs, OPDEFs, and accumulator
03100 definitions is available to provide accessability to this table for
03200 assembly language routines. This file may be concatenated to a FAIL
03300 program before assembly. Users can read and modify these entries in
03400 SAIL via the procedure Usercon, 12-120.
03500
03600
03700 17-4. Most execution-time routines load the address contained in
03800 GOGTAB into the accumulator USER (currently '15) in order to index
03900 the user table. Thus in what follows, symbolic index XX into this
04000 table will be listed as XX(USER).
04100
04200
04300 Storage Allocation Routines
04400
04500
04600 17-5. SAIL makes all requests for storage through the routines
04700 CORGET, CORREL, CORINC, CORBIG, and CANINC. These routines are
04800 described in the following paragraphs. The AC's THIS and SIZ are
04900 currently set to 2 and 3, respectively. All core routines are called
05000 with PUSHJ 17,routine.
00100 SAILON NO. 57.2 SAIL 17-5
00200
00300
00400
00500 Corget
00600
00700
00800 17-6. Corget is called with the desired size of a block of storage
00900 in register SIZ. It returns the address of the new block in THIS.
01000 No other accumulators are altered. Normally the function skips on
01100 return. It does not skip if insufficient core is available to grant
01200 the request. The address returned is that of the first free data
01300 word (DATA below).
01400
01500
01600 17-7. A SAIL core block has the following form:
01700
01800
01900 HEAD: →LAST,,→NEXT ;when not in use (free list links)
02000 SIZE ;END-HEAD+1, negated when block is in use
02100 DATA: BLOCK SIZE-3 ;available to user -- sometimes a few more
02200 ; words than requested will be contained
02300 ; in the block
02400 END: USEBIT,,→HEAD ;USEBIT is 400000 if block is in use; else 0
02500
02600 The first time CORGET is called, GOGTAB is 0. CORGET notices this
02700 and performs the following special actions:
02800
02900 1) Prepares to allocate storage just past the program and
03000 symbols (left half of JOBSA contains the relevant address).
03100
03200 2) Allocates the user table; puts pointer in GOGTAB.
03300
03400 3) Forms remaining free storage from the end of the user table
03500 to contents (JOBREL) [C(JOBREL)] into a single free SAIL
03600 block. Puts →HEAD in LO(USER), FRE(USER). Puts C(JOBREL)+1
03700 in TOP(USER).
03800
03900 4) Performs the requested CORGET operation.
04000
04100
04200 17-8. FRE(USER) is the header of a linked free storage list,
04300 Blocks are obtained from this list and the list is updated. CORREL
04400 releases blocks onto this list. If no currently free block will
04500 satisfy a CORGET request, the CORE UUO is executed to get more from
04600 the time sharing system.
00100 SAILON NO. 57.2 SAIL 17-9
00200
00300
00400
00500 17-9. Users are free to use the CORGET function if they will be
00600 careful of the two header words and the single trailer word
00700 associated with each block. Release these blocks as soon as possible
00800 to prevent undue checker-boarding of free storage.
00900
01000
01100 Correl
01200
01300
01400 17-10. Correl is called with the address obtained in the
01500 corresponding Corget call (the DATA address) in register THIS. The
01600 block is returned to the free storage list. If either of the two
01700 neighboring blocks is already free, the adjacent free blocks are
01800 merged with the one being released to form a bigger one. If the
01900 block being released is uppermost in core, and if it occupies more
02000 than about 2K, the core size of the program is contracted using the
02100 CORE UUO. About 2K of free storage is left in this case. No ACs are
02200 altered by CORREL.
02300
02400
02500 Corinc
02600
02700
02800 17-11. Corinc is called with the DATA address of a SAIL block in
02900 THIS and a desired increment in SIZ. If there is a free block
03000 directly above the THIS block with at least SIZ free words, or if the
03100 THIS block occupies the highest addresses of any block in use, the
03200 request is granted, the block is extended by SIZ words and the
03300 function executes a skip-return. Otherwise no skip occurs and no
03400 action is taken. No ACs will be altered.
03500
03600
03700 Caninc
03800
03900
04000 17-12. Caninc performs the same tests as Corinc and skips under
04100 the same conditions. It also uses the same calling sequence. If it
04200 does not skip, it returns with SIZ altered to show the number of
04300 words by which the DATA block can be increased. It is 0 if no
04400 increase is possible. This function never affects current core
04500 allocation.
00100 SAILON NO. 57.2 SAIL 17-13
00200
00300
00400
00500 Corbig
00600
00700
00800 17-13. Corbig returns the size of the largest available free block
00900 in SIZ.
01000
01100
01200 17-14. These functions are not available to SAIL programs since
01300 core can be obtained by array declarations (which in turn use these
01400 functions).
01500
01600
01700 STRINGS
01800
01900 String Descriptors
02000
02100
02200 17-15. A SAIL String has two distinct parts: the descriptor and
02300 the text. The descriptor is unique and has the following format:
02400
02500
02600 WORD1: STRINGNO,,LENGTH
02700 WORD2: BYTP
02800
02900
03000 1) STRINGNO. This entry is 0 if the String is a constant (the
03100 descriptor will not be altered, and the String text is not
03200 in String space, is therefore not subject to garbage
03300 collection). Every time a String is created via the
03400 concatenation operator, or Input function, or an
03500 Integer-String type conversion, it receives a new STRINGNO.
03600 Each new String receives a number one greater than the last,
03700 starting at 1 when the program is initialized. All strings
03800 formed as substrings of a given String have the String
03900 number of the original (major) string. These numbers aid in
04000 increasing String garbage collection efficiency.
04100
04200 2) LENGTH. This number is zero for any null String; otherwise
04300 it is the number of text characters.
04400
04500 3) BYTP. If count is 0, this byte pointer is never checked (it
04600 need not even be a valid byte pointer. Otherwise, an ILDB
04700 machine instruction pointed at the BYTP word will retrieve
04800 the first text character of the String. The text for a
04900 String may begin at any point in a word. The characters are
05000 stored as LENGTH contiguous characters.
00100 SAILON NO. 57.2 SAIL 17-16
00200
00300
00400
00500 17-16. A SAIL String variable contains the two word descriptor for
00600 that variable. The identifier naming it points to WORD1 of that
00700 descriptor. If a String is declared INTERNAL, a symbol is formed to
00800 reference WORD2 by taking all characters from the original name (up
00900 to 5) and concatenating a "." (OUTSTRING's second word would be
01000 labeled OUTST.).
01100
01200
01300 17-17. When a String is passed by reference to a procedure, the
01400 address of WORD2 is placed in the P-stack (see PROCEDURE
01500 IMPLEMENTATION, 17-48). For VALUE Strings both descriptor words are
01600 pushed onto the SP stack.
01700
01800
01900 17-18. A String array is a block of 2-word String descriptors.
02000 The array descriptor (see ARRAY IMPLEMENTATION, 17-35) points at the
02100 second word of the first descriptor in the array.
02200
02300
02400 17-19. Information is generated by the compiler to allow the
02500 locations of all non-constant strings to be found for purposes of
02600 garbage-collection and initialization (see PROCEDURE IMPLEMENTATION,
02700 17-48). All String variables and arrays are cleared to NULL whenever
02800 a SAIL program is started.
02900
03000
03100 String Operations
03200
03300
03400 17-20. The five basic String operations are concatenation (CAT),
03500 substrings (SUBSTR), String-integer (done inline), Integer-string
03600 (PUTCH), and one-character truncation (LOP, compiled inline). Other
03700 functions producing or operating upon strings are described in
03800 Execution Routines, 12-1.
00100 SAILON NO. 57.2 SAIL 17-21
00200
00300
00400
00500 Cat
00600
00700
00800 17-21. CAT forms a new String from two other strings (constants or
00900 otherwise). The calling sequence is:
01000
01100
01200 PUSH SP,WORD11 ;WORD1, FIRST ARGUMENT
01300 PUSH SP,WORD12 ;WORD2, FIRST ARGUMENT
01400 PUSH SP,WORD21 ;ETC.
01500 PUSH SP,WORD22
01600 PUSHJ P,CAT
01700
01800 The result is found as a new two-word descriptor on top of the SP
01900 (currently AC '16) stack. If either argument is the null String, the
02000 result is the other argument. If the first argument occupies the
02100 space directly preceding the first free character in String space,
02200 only the second argument is copied. Otherwise, both arguments are
02300 copied (in order) into free space to form the result. A new String
02400 number is created for this result. The LENGTH field is the sum of
02500 the LENGTHs of the two arguments.
02600
02700
02800 Substr
02900
03000
03100 17-22. SUBSTR returns a descriptor representing a part of its
03200 input argument. SUBSTR is really two routines, called as follows:
03300
03400
03500 PUSH SP,WORD1
03600 PUSH SP,WORD2
03700
03800 SUBST SUBSR
03900 PUSH P,LASDX PUSH P,NUMCHR
04000 PUSH P,FIRSDX PUSH P,FIRSDX
04100
04200 PUSHJ P,SUBS{T/R}
04300
04400 LASDX is the number of the last character to be included (starting
04500 with 1). FIRSDX is the number of the first character to be included.
04600 NUMCHR is the number of characters to be included.
00100 SAILON NO. 57.2 SAIL 17-23
00200
00300
00400
00500 17-23. The result is always a two-word descriptor in the SP stack
00600 describing the substring.
00700
00800 SUBST is used for the construct ST[X for Y].
00900 SUBSR is used for ST[X to Y].
01000
01100
01200 17-24. An error code is returned if the request can not be totally
01300 satisfied (see Substrings, 9-42).
01400
01500
01600 17-25. The String number of the output is the same as the String
01700 number of the input.
01800
01900
02000 String to Integer
02100
02200
02300 17-26. This returns the first string character (or 0),
02400 right-justified, in an accumulator. It is invoked when something
02500 like I←STR is executed (see String-Arithmetic Conversions, 9-27). It
02600 is compiled as
02700
02800
02900 HRRZ AC,WORD1
03000 JUMPE AC,.+3
03100 MOVE AC,WORD2
03200 ILDB AC,AC
03300
03400
03500
03600 Putch
03700
03800
03900 17-27. Call with
04000
04100
04200 PUSH P,VALUE
04300 PUSHJ P,PUTCH
04400
04500 The result is a String descriptor with count of 1 on top of the SP
04600 stack. The P stack is adjusted to remove the parameter and return
04700 address. The String number is new. The low order 7 bits of VALUE
04800 form the single character in the string.
00100 SAILON NO. 57.2 SAIL 17-28
00200
00300
00400
00500 Lop Details
00600
00700
00800 17-28. LOP(ST) is compiled inline as:
00900
01000
01100 HRRZ AC,WORD1
01200 JUMPE AC,.+3
01300 ILDB AC,WORD2 ;return 1st char, update bp
01400 SOS WORD1 ;decrement character count
01500
01600
01700
01800 String Space
01900
02000
02100 17-29. The normal or user-specified (see STORAGE ALLOCATION,
02200 14-22) number of words required for strings is used to obtain a
02300 single SAIL block (see Storage Allocation Routines, 17-5) when the
02400 program is started. The limits of this area are placed in ST(USER)
02500 and STTOP(USER). Other parameters are set up as described below.
02600
02700
02800 17-30. String text characters are placed contiguously in thes area
02900 as strings are created. When not enough storage remains for a
03000 contemplated String, the garbage collector (see String Garbage
03100 Collection, 17-32) is called to obtain more (by compacting the
03200 current space, if possible). If this fails, the program will restart
03300 and request more reasonable allocation.
00100 SAILON NO. 57.2 SAIL 17-31
00200
00300
00400
00500 Parameters Used by String Operations
00600
00700
00800 17-31.
00900
01000 ST(USER) Bottom (low address) of String space
01100
01200 STTOP(USER) (Top+1) of String space
01300
01400 TOPBYTE(USER) Byte pointer such that IDPB TOPBYTE(USER) will
01500 store into next character
01600
01700 REMCHR(USER) Negated number of free characters remaining
01800
01900 TOPSTR(USER) WORD1 for last created String (doesn't include
02000 substring operations). CAT uses this word to
02100 decide whether its first argument needs to be
02200 moved (see Cat, 17-21).
02300
02400
02500 String Garbage Collection
02600
02700
02800 17-32. The String garbage collector (STRNGC) is called whenever
02900 the (estimated or actual) size of a soon-to-be-created String is
03000 larger than -REMCHR(USER). By various devious means it finds all
03100 active (non-constant) String descriptors, sorting them in ascending
03200 address sequence by using the byte pointers, associating all
03300 substrings of a given active String (major String) ...ouch. Then it
03400 compacts String space by moving the text for all major strings to
03500 lower memory locations occupied by text no longer reachable from any
03600 descriptor. Finally it updates all String descriptors and the
03700 parameters described above. If there is still not enough room, it
03800 prints a frustrated message and restarts the program with the
03900 allocation sequence normally obtained by typing the REEnter system
04000 command (see STORAGE ALLOCATION, 14-22).
00100 SAILON NO. 57.2 SAIL 17-33
00200
00300
00400
00500 String-Oriented Machine Language Routines
00600
00700
00800 17-33. If you must write a routine which operates on strings,
00900 please observe the following conventions:
01000
01100 1) See PROCEDURE IMPLEMENTATION, 17-48 for conventions
01200 concerning input parameters and value returning.
01300
01400 2) If you merely need to read a String, no particular care is
01500 required (don't change the descriptor of a reference String
01600 parameter by performing careless ILDBs).
00100 SAILON NO. 57.2 SAIL 17-34
00200
00300
00400
00500 17-34. If you need to create a new String, these are also
00600 applicable:
00700
00800 4) Estimate the number of characters if it is not known
00900 exactly. This estimate must be an upper bound; an
01000 unrealistically large estimate will cause the garbage
01100 collector to work more often than necessary. Place the
01200 estimate in register A (1).
01300
01400 4) Execute the following code before doing any
01500 String-munching:
01600
01700
01800 MOVE USER,GOGTAB ;ESTABLISH ADDRESSABILITY
01900 ADDM A,REMCHR(USER) ;UPDATE REMAINING COUNT
02000 SKIPLE REMCHR(USER) ;TEST IMPENDING OVERFLOW
02100 PUSHJ P,STRNGC ;COLLECT, WILL NOT RETURN IF
02200 ; NEW REMCHR+C(A)>0.
02300
02400
02500 5) TOPBYTE(USER) should be your WORD2 result. Save it now.
02600
02700 6) Do repeated IDPBs to TOPBYTE(USER) to store your string.
02800 This keeps TOPBYTE accurate. Count characters if your
02900 estimate was only an estimate.
03000
03100 7) Create WORD1 of your result. The left half is the left
03200 half of TOPSTR(USER) incremented by one. The right half is
03300 the length of your new string. This word is not only WORD1
03400 of your result, but also should be placed in TOPSTR(USER).
03500
03600 8) Subtract (estimate - actual length) from REMCHR(USER) to
03700 keep it honest. This should make REMCHR if anything more
03800 negative.
03900
04000 9) Return String results on the top of the SP stack. If a
04100 result is to go in a reference parameter (see PROCEDURE
04200 IMPLEMENTATION, 17-48) remember that the address you have
04300 is that of the WORD2 (byte pointer) word of the descriptor.
00100 SAILON NO. 57.2 SAIL 17-35
00200
00300
00400
00500 ARRAY IMPLEMENTATION
00600
00700 Form
00800
00900
01000 17-35. Let STRINGAR be 1 (TRUE) if the array in question is a
01100 String array, 0 (FALSE) otherwise. Then a SAIL array of n dimensions
01200 has the following format:
01300
01400
01500 HEAD: →DATAWD ;→ MEANS "POINTS AT"
01600 HEAD-END-1
01700 ARRHED: BASE_WORD ;SEE BELOW
01800 LOWER_BD(n)
01900 UPPER_BD(n)
02000 MULT(n)
02100 ...
02200 LOWER_BD(1)
02300 UPPER_BD(1)
02400 MULT(1)
02500 NUM_DIMS,,TOTAL_SIZE
02600 DATAWD: BLOCK TOTAL_SIZE
02700 <sometimes a few extra words>
02800 END: 400000,,→HEAD
02900
03000
03100
03200 Explanation
03300
03400
03500 17-36.
03600
03700 HEAD The first two words of each array, and the last, are
03800 control words for the Storage Allocation Routines,
03900 17-5. These words are always present for an array.
04000 The array access code does not refer to them.
04100
04200 ARRHED Each array is preceded by a block of 3*n+2 control
04300 words. The BASE_WORD entry is explained later.
04400
04500 NUM_DIMS This is the dimensionality of the array. If STRINGAR,
04600 this value is negated before storage in the left half.
04700
04800 TOTAL_SIZE The total number of accessible elements (double if
04900 STRINGAR) in the array.
00100 SAILON NO. 57.2 SAIL 17-36
00200
00300
00400 BOUNDS The lower bound and upper bound for each dimension are
00500 stored in this table, the left-hand index values
00600 occupying the higher addresses (closest to the array
00700 data). If they are constants, the compiler will
00800 remember them too and try for better code (i.e.
00900 immediate operands).
01000
01100 MULT This number, for dimension m, is the product of the
01200 total number of elements of dimensions m+1 through n.
01300 MULT for the last dimension is always 1.
01400
01500 BASE_WORD This is
01600
01700 DATAWD - the sum of (STRINGAR+1)*LOWER_BD(m)*MULT(m)
01800
01900 for all m from 1 to n. The formula for calculating
02000 the address of A[I,J,K] is:
02100
02200
02300 address(A[I,J,K]) =
02400 address(DATAWD) +
02500 (I-LOWER_BD(1))*MULT(1) +
02600 (J-LOWER_BD(2))*MULT(2) +
02700 (K-LOWER_BD(3))
02800
02900 This expands to
03000
03100
03200 address(A[I,J,K]) =
03300 address(DATAWD) +
03400 I*MULT(1) + J*MULT(2) + K
03500 -(LOWER_BD(1)*MULT(1) + LOWER_BD(2)*MULT(2) + LOWER_BD(3)
03600
03700 which is
03800
03900
04000 BASE_WORD + I*MULT(1) + J*MULT(2) + K.
04100
04200 By pre-calculating the effects of the lower bounds,
04300 several instructions are saved for each array
04400 reference.
00100 SAILON NO. 57.2 SAIL 17-37
00200
00300
00400
00500 Array Allocation
00600
00700 Dynamic Arrays
00800
00900
01000 17-37. When an array is declared in any block other than the outer
01100 one, the compiler generates code to call the function ARMAK with
01200 parameters describing the array. This routine calls CORGET (see
01300 Storage Allocation Routines, 17-5) to obtain enough storage, then
01400 sets up the control table and clears the data area to zeroes. The
01500 ARRHED address is saved in an array push-down list whose pointer is
01600 ARRPDP(USER). The address of DATAWD+1 is returned for String arrays;
01700 the address of DATAWD is returned for all others. The compiler
01800 generates code to store this address in the core cell bearing the
01900 name of the array variable.
02000
02100
02200 17-38. When all declarations for a block containing array
02300 declarations have been processed, the compiler issues a call to ARMRK
02400 which marks the array push-down stack (with a -1, as a matter of
02500 fact). On block exit (or when a GO TO transfers out of the block),
02600 the routine ARREL is called to remove this mark and return all arrays
02700 back to the previous mark to the SAIL free storage list.
02800
02900
03000 17-39. The String garbage collector uses the array push-down stack
03100 to find dynamic String arrays which need attention.
03200
03300
03400 Built-In Arrays
03500
03600
03700 17-40. Outer-block arrays have constant bounds. The compiler
03800 simply emits a Jrst instruction, then compiles the control table into
03900 the block head of the object program. It leaves room for the array,
04000 then issues the END word. The Jrst instruction then finds its home
04100 in some code to clear the array to zeroes.
04200
04300
04400 17-41. The core location bearing the name of the array has the
04500 address of DATAWD (DATAWD+1 if STRINGAR) compiled into it. This
04600 address is given the dotted name described in DEBUGGING, 15-9.
00100 SAILON NO. 57.2 SAIL 17-42
00200
00300
00400
00500 17-42. For built-in String arrays, a String link block (see
00600 PROCEDURE IMPLEMENTATION, 17-48) is issued following the space
00700 allocated for the array. The String garbage collector (see String
00800 Garbage Collection, 17-32) gains access to this array through this
00900 static link.
01000
01100
01200 17-43. It can be seen from all this that all dynamic and built-in
01300 arrays are cleared when the blocks in which they are declared are
01400 entered. Since the outer block of a separately compiled procedure
01500 file (see Separately Compiled Procedures, 16-7) is never entered, its
01600 built-in arrays, although available for use, are never cleared. The
01700 loader clears them once as it loads.
01800
01900
02000 Array Access Code
02100
02200
02300 17-44. In the worst case (no fixed bounds, bounds checking, not
02400 built-in) the statement K←A[I,J] will be compiled as:
02500
02600
02700 MOVE 1,A ;→FIRST DATA WORD
02800 MOVE 2,I ;FIRST SUBSCRIPT
02900 CAML 2,-4(1) ;IF <LOWER BOUND OR
03000 CAMLE 2,-3(1) ; >UPPER BOUND THEN
03100 ARERR 1,[ASCIZ /A/] ; ERROR IN INDEX 1
03200 IMUL 2,-2(1) ;I*MULT(1)
03300 MOVE 3,J ;CHECK DIMENSION 2
03400 CAML 3,-7(1)
03500 CAMLE 3,-6(1)
03600 ARERR 2,[ASCIZ /A/]
03700 ADD 3,2 ;NO MULT FOR LAST, COLLECT OFFSET
03800 ADD 3,-10(1) ; + BASE_WORD
03900 MOVE 4,(3) ;DATA FROM A[I,J]
04000 MOVEM 4,K
04100
00100 SAILON NO. 57.2 SAIL 17-45
00200
00300
00400
00500 17-45. If A is, however, declared in the outer block as SAFE
00600 INTEGER ARRAY A[1:10,1:5], the code for A[I,J] is
00700
00800
00900 MOVE 1,I
01000 IMULI 1,5 ;I*MULT(1)
01100 ADD 1,J ;COLLECT OFFSET
01200 MOVE 2,A.-5(1) ;CONSTANT PART OF ADDRESS COMPILED IN
01300 MOVEM 2,K
01400
01500
01600
01700 17-46. A[I,3] would be compiled as
01800
01900
02000 MOVE 1,I
02100 IMULI 1,5
02200 MOVE 2,A.-2(1)
02300 MOVEM 2,K
02400
02500 and J←A[2,3] would be
02600
02700 MOVE 3,A.+7
02800 ...
02900 MOVEM 3,J
03000
03100
03200 17-47. Various configurations of array declarations and accesses
03300 result in code which ranges between these degrees of efficiency.
03400
03500
03600 PROCEDURE IMPLEMENTATION
03700
03800
03900 17-48.
04000
04100
04200 Procedure Body
04300
04400
04500 17-49. To describe the main characteristics of SAIL procedures, a
04600 set of sample procedures are displayed here along with the code they
04700 produce. Some of the entries are discussed in more detail below.
04800 The notation [n] is placed in the comment field of the assembly
04900 instruction to refer to these discussions:
00100 SAILON NO. 57.2 SAIL 17-49
00200
00300
00400
00500 INTEGER PROCEDURE P1(INTEGER I,J; STRING A);
00600 P1: AOS P1PAC ;[1] INCREMENT PROC ACTIVE COUNTER
00700
00800 BEGIN
00900 INTEGER Q; STRING A,B;
01000 INTEGER ARRAY X[0:5];
01100 PUSH P,[0]
01200 PUSH P,[5]
01300 PUSH P,[1]
01400 PUSHJ P,ARMAK ;ALLOCATE AND CLEAR
01500 MOVEM 1,X ;STORE POINTER
01600 PUSHJ P,ARMRK ;END OF ARRAYS FOR BLOCK
01700
01800
01900 <code for procedure>
02000
02100 RETURN(Q);
02200 MOVE 1,Q ;[2] RESULT IN 1
02300 PUSHJ P,ARREL ;[3] RELEASE ARRAYS FOR BLOCK
02400 JRST P1EXIT ;EXIT PROCEDURE
02500
02600 <more code for procedure>
02700
02800
02900 END "P1"
03000 PUSHJ P,ARREL ;IF FALLS THROUGH, RELEASE ARRAYS
03100 P1EXIT: SOS P1PAC ;ONE TIME LESS ACTIVE
03200 SUB SP,[XWD 2,2] ;REMOVE STRING PARAMETER
03300 SUB P,[XWD 3,3] ;[4] NON-STRINGS, RETURN ADDR
03400 JRST @3(P) ;RETURN
03500 Q: 0 ;ROOM FOR VARIABLE
03600 X: 0 ;ARRAY POINTER
03700 TEMP07: 0 ;[5] TEMPORARY STORAGE
03800 A: BLOCK 2 ;TWO WORDS FOR EACH STRING
03900 B: BLOCK 2
04000 P1PAC: 0 ;[6] PROCEDURE-ACTIVE COUNT
04100 XWD 2,A ;STRING COUNT,→FIRST
04200 LNKWD: 0 ;[7] LINK PASSES THROUGH HERE
04300 LINK 1,LNKWD ;[7] CAUSES LOADER LINKAGE
04400
04500
04600
04700
04800 PROCEDURE P2(INTEGER I,J; STRING A);
04900 BEGIN
05000 INTEGER ARRAY X[0:10];
05100 ...
00100 SAILON NO. 57.2 SAIL 17-49
00200
00300 BEGIN
00400 INTEGER ARRAY Y[0:10];
00500 ...
00600 RETURN;
00700 PUSHJ P,ARREL ;RELEASE ARRAYS FOR ALL
00800 PUSHJ P,ARREL ; BLOCKS IN PROCEDURE
00900 JRST P2EXIT
01000
01100 ...
01200 END;
01300 END"P2";
01400
01500
01600
01700 STRING PROCEDURE P3(STRING A,B);
01800 BEGIN STRING C;
01900 ...
02000 RETURN(C);
02100 SUB SP,[XWD 4,4] ;REMOVE PARAMS
02200 PUSH SP,C
02300 PUSH SP,C+1 ;RETURN STRING RESULT
02400 JRST P3EXIT
02500
02600 RETURN(B);
02700 SUB SP,[XWD 4,4]
02800 PUSH SP,3(SP) ;FIRST WORD OF B
02900 PUSH SP,3(SP) ;SECOND WORD OF B
03000 JRST P3EXIT ;GO RETURN
03100
03200 RETURN(C&"STR"); COMMENT ASSUME CAT ALREADY DONE;
03300 SUB SP,[XWD 6,6] ;REMOVE PARAMS, TEMP RESLT
03400 PUSH SP,5(SP) ;TEMP RESLT
03500 PUSH SP,5(SP) ;2D WORD
03600 JRST P3EXIT
03700
03800 ...
03900 END "P3";
04000 P3EXIT: SOS P3PAC
04100 SUB SP,[XWD 4,4] ;NOT THIS TIME, BUT WOULD
04200 PUSH SP,[0] ;BE INCLUDED IF NO RETURNS
04300 PUSH SP,[0] ;DONE ABOVE (RETURN NULL STRING)
04400
04500
04600 RECURSIVE INTEGER PROCEDURE P4(STRING A,B; INTEGER I,J);
04700 P4TEXT: AOS P4PAC
04800
04900 BEGIN
05000 STRING C,D; INTEGER K,L;
05100 ...
00100 SAILON NO. 57.2 SAIL 17-49
00200
00300 END "P4";
00400 P4EXIT: SOS P4PAC
00500 SUB SP,[XWD =8,=8] ;[8]TAKE OFF LOCALS,PARAMS
00600 HRRI TEMP,C ;[8]
00700 HRLI TEMP,5(SP) ;[8]
00800 BLT TEMP,D+1 ;[8] RESTORE LOCAL STRINGS
00900
01000 SUB P,[XWD 6,6] ;[8] SAME FOR P-SIDE
01100 HRRI TEMP,K ; (ALSO RETURN ADDR REMOVED)
01200 HRLI TEMP,4(P)
01300 BLT TEMP,TEMP03 ;MUST EVEN SAVE TEMPS
01400 JRST @3(P) ;RETURN
01500
01600 P4: ADD P,[XWD 3,3] ;LEAVE ROOM FOR LOCALS
01700 SKIPL P ;CHECK PUSH-DOWN OVERFLOW
01800 PDLOV P, ;[9]UUO TO SIMULATE PDL OV
01900 HRRI TEMP,-2(P) ;[9]SAVE LOCALS
02000 HRLI TEMP,TEMP03 ; AND TEMPS
02100 BLT TEMP,(P)
02200 <similarly for SP (string stack)>
02300 JRST P4TEXT ;GO DO PROCEDURE
02400 <variables and such>
02500
02600
02700
02800 RECURSIVE STRING PROCEDURE P5(STRING A,B);
02900 BEGIN
03000 STRING C,D;
03100 ...
03200 RETURN(C);
03300 PUSHJ P,P5POP ;[10]REMOVE STRING LOCALS,PARAMS
03400 PUSH SP,C ;STRING RESULT
03500 PUSH SP,C+1
03600 PUSHJ P,ARREL ;ENOUGH TIMES IF ANY ARRAYS
03700 JRST P5EXIT
03800
03900 RETURN(B);
04000 PUSHJ P,P5POP
04100 PUSH SP,3(SP)
04200 PUSH SP,3(SP) ;RETURN PARAMETER
04300 JRST P5EXIT
04400
04500 RETURN(A&"STR");
04600 POP SP,1 ;[11]ASSUME CAT ALREADY DONE
04700 POP SP,0
04800 PUSHJ P,P5POP
04900 PUSH SP,0 ;[11]RETURN VALUE
05000 PUSH SP,1
05100 JRST P5EXIT
00100 SAILON NO. 57.2 SAIL 17-49
00200
00300
00400 ...
00500 END "P5";
00600 P5EXIT: SUB P,[XWD 2,2] ;OR WHATEVER, SEE ABOVE
00700 ... ;RESTORE LOCALS, ADJUST
00800 JRST @3(P) ;RETURN
00900
01000 P5: <as above>
01100 ...
01200
01300 P5POP: SUB SP,[XWD =8,=8] ;[10] REMOVE STRING LOCALS,PARAMS
01400 HRRI TEMP,C
01500 HRLI TEMP,5(SP)
01600 BLT TEMP,D+1
01700 POPJ P, ;RETURN
01800
01900 The main program has the following format:
02000
02100
02200 S.: SKIPA ;NOT STARTED IN RPG MODE
02300 SETOM RPGSW ;STARTED IN RPG MODE -- RPGSW A GLOBAL
02400 JSR SAILOR ;INIT -- RETURNS BY PUSHJ P,@SAILOR
02500
02600 Comment ⊗ The main program looks like a non-recursive procedure
02700 from here on, except for built-in arrays ⊗
02800
02900 POPJ P, ;RETURN TO INIT, WHO EXITS
03000 <global variables, linkages>
03100 <non-String constants>
03200 XWD 0,,=8 ;TYPICAL STRING CONSTANT
03300 POINT 7,.+1
03400 ASCII /CONSTANT/
03500 <more String constants>
03600
03700 END S. ;STARTING ADDRESS FOR MAIN PROGRAM
03800
00100 SAILON NO. 57.2 SAIL 17-50
00200
00300
00400
00500 Discussion
00600
00700
00800 17-50.
00900
01000 [1] There is for each procedure a word (PAC for Procedure Active
01100 Count) which is incremented on procedure entry and decremented
01200 on exit. At one time, the String garbage collector used this
01300 word. It may again some time in the future. At present the
01400 counter is useful for determining the depth of recursion (from
01500 DDT).
01600
01700 [2] Non-String procedures return their results in 1; Fortran
01800 returns things in 0; String results are returned on the SP
01900 stack.
02000
02100 [3] An ARREL call is issued for each block (containing arrays)
02200 which must be left in order to exit. All arrays for these
02300 blocks are released at this time. The same sort of thing
02400 happens when a Go To statement leaves one or more blocks.
02500
02600 [4] Since the return address is on the top of the P-stack, with
02700 parameters buried beneath, a subtract and an indirect jump
02800 replace the POPJ. Procedures always adjust the stack before
02900 returning.
03000
03100 [5] String temporaries are kept in the SP stack. Others
03200 occasionally occupy core locations. These are grouped with
03300 the non-String variables to make saving and restoring easy in
03400 recursive procedures.
03500
03600 [6] This is the Procedure Active Count word (see [1]). It is
03700 placed in a fixed location with respect to the String-link
03800 block (below). The String garbage collector could, if it
03900 wished, see this count.
04000
04100 [7] A linked list, with its head in a reserved cell in the user
04200 table (see User Table, 17-1) gives the String garbage collector
04300 access to all String variables declared for each procedure; and
04400 to all built-in String arrays. Each entry on the list contains
04500 three words: a PAC counter (currently ignored), a word giving
04600 the location and extent of the String descriptors being
04700 described, and the pointer (LNKWD) to the next entry. A 0
04800 entry ends the list. The LINK pseudo-op (or the equivalent
04900 code issued by SAIL) instructs the loader to create this list.
05000 The LINKEND pseudo-op is issued in the SAILOR routine to
05100 collect the address of the first list element. This is then
00100 SAILON NO. 57.2 SAIL 17-50
00200
00300 transferred to the user table. See [Weiher] for details
00400 concerning the LINK block type.
00500
00600 [8] When a recursive procedure is called, all values for variables
00700 declared in blocks internal to this procedure are saved in the
00800 appropriate stack. These are added "on top of" the parameters
00900 and return address for the procedure. At procedure exit the
01000 stack pointer is adjusted to point below the first parameter.
01100 Then the proper BLT word is set up to restore all these locals
01200 from the stack. After the BLT is executed, that stack is ready
01300 for procedure exit.
01400
01500 [9] Since SAIL is a one-pass compiler, it does not know how many
01600 locals a procedure has until all blocks for that procedure have
01700 been processed. Therefore the entry code for recursive
01800 procedures is added last, followed by a jump to the procedure
01900 text.
02000
02100 [10] When a String procedure returns a value, the String parameters
02200 and locals must be removed from the stack before the value
02300 (result) can be pushed on. Since the total number of String
02400 locals is not yet known, a routine like P5POP is called to
02500 remove the unwanted values first. Recursive String procedures
02600 must contain Return Statements (see Return Statement, 5-20);
02700 otherwise improper code will result.
02800
02900 [11] Once P5POP or its equivalent has been executed, the previous
03000 top of stack location is not known; the temp value is therefore
03100 removed first and restored after the call.
03200
03300
03400 Procedure Calling Sequences
03500
03600
03700 17-51. Again a case study is presented. A procedure with several
03800 internal procedures is presented to demonstrate the ridiculous number
03900 of possibilities. Only the relevant code is described. Accumulator
04000 numbers in the code below are only examples -- other values are
04100 possible. This list is not complete; to describe all cases here
04200 would take more space than a copy of the code in SAIL which handles
04300 them. Item and Set parameters behave like Integer and Real
04400 parameters as far as argument passing is concerned:
00100 SAILON NO. 57.2 SAIL 17-51
00200
00300
00400
00500 PROCEDURE SUPER(REFERENCE STRING RPSTR;
00600 INTEGER PINT; REFERENCE INTEGER RPINT;
00700 REAL PROCEDURE PPAR;
00800 STRING PSTR1,PSTR2);
00900 BEGIN
01000 INTEGER INT1,INT2; STRING STR1,STR2; REAL REL;
01100 SAFE INTEGER ARRAY ARR[2:10]; SAFE STRING ARRAY SARR[2:10];
01200 INTEGER PROCEDURE INTP(INTEGER I,J);...;
01300 PROCEDURE RINTP(REFERENCE INTEGER I);...;
01400 PROCEDURE STRP(STRING A,B);...;
01500 PROCEDURE RSTRP(REFERENCE STRING A);...;
01600 PROCEDURE PROCP(PROCEDURE PARAM);...;
01700 PROCEDURE ARRP(STRING ARRAY X);...;
01800
01900
02000 INT1←PINT↑2 + RPINT↑2 - 3;
02100 MOVE 1,-3(P) ;RELATIVE LOC OF PINT
02200 IMUL 1,1
02300 MOVE 2,@-2(P) ;RPINT's ADDRESS IS IN STACK
02400 IMUL 2,2
02500 ADD 2,1 ;SUM
02600 SUBI 2,3 ;RESULT LEFT IN 2
02700
02800 REL←INTP(INT1,PINT);
02900 PUSH P,2 ;INT1 STILL IN 2
03000 PUSH P,-4(P) ;[1]ADJUST FOR PREV PUSH
03100 MOVEM 2,INT2 ;[2]STORE CURRENT ACS BEFORE CALL
03200 PUSHJ P,INTP ;CALL PROCEDURE
03300 FLOAT 1,1 ;CONVERT TO REAL -- REL IS IN 1
03400
03500 RINTP(INT1);
03600 PUSH P,[INT1] ;ADDRESS OF INT1
03700 MOVEM 1,REL ;PREVIOUS RESULT
03800 PUSHJ P,RINTP
03900
04000 RINTP(PINT);
04100 MOVEI 3,-3(P) ;ADDRESS OF PINT
04200 PUSH P,3
04300 PUSHJ P,RINTP
04400
04500 RINTP(RPINT);
04600 PUSH P,-2(P) ;PASS ON ADDR OF RPINT
04700 PUSHJ P,RINTP
04800
04900 INT2←INTP(INT1,ARR[PINT]);
05000 PUSH P,INT1
05100 MOVE 4,-4(P) ;PINT
00100 SAILON NO. 57.2 SAIL 17-51
00200
00300 MOVE 5,ARR
00400 ADD 4,-4(5) ;BASE ADDR OF ARR
00500 PUSH P,(4)
00600 PUSHJ P,INTP ;RESULT IN 1
00700
00800 RINTP(ARR[PINT]);
00900 MOVE 6,PINT
01000 MOVE 7,ARR
01100 ADD 6,-4(7)
01200 PUSH P,6 ;ADDRESS
01300 MOVEM 1,INT2
01400 PUSHJ P,RINTP
01500
01600 STRP(STR1&"CON",PSTR1);
01700 PUSH SP,STR1
01800 PUSH SP,STR1+1
01900 PUSH SP,CONAD ;ADDRESS OF DSCRPTR FOR "CON"
02000 PUSH SP,CONAD+1
02100 PUSHJ P,CAT ;LEAVE CONCATENATE IN STACK
02200 PUSH SP,-4(SP) ;PUT STR1 ON TOP
02300 PUSH SP,-4(SP)
02400 PUSHJ P,STRP
02500
02600 RSTRP(STR1);
02700 PUSH P,[STR1+1] ;ALL REF PARAMS TO P-STACK
02800 PUSHJ P,RSTRP
02900
03000 RSTRP(RPSTR);
03100 PUSH P,-4(P) ;PASS REFERENCE ALONG;
03200 PUSHJ P,RSTRP
03300
03400 RSTRP(PSTR2);
03500 HRROI 10,(SP) ;[3]RH→2D WORD OF PSTR2
03600 PUSH P,10
03700 PUSHJ P,RSTRP
03800
03900 PROCP(RINTP);
04000 PUSH P,[RINTP] ;PARAMETRIC PROCEDURE
04100 PUSHJ P,PROCP
04200
04300 ARRP(SARR);
04400 PUSH P,SARR ;THIS IS EFFECTIVELY A REFERENCE CALL
04500 PUSHJ P,ARRP
04600
00100 SAILON NO. 57.2 SAIL 17-52
00200
00300
00400
00500 Discussion
00600
00700
00800 17-52.
00900
01000 [1] Counts are maintained of the current number of actual
01100 parameters (during a procedure call) on each stack. These
01200 counts must be added to the parameter indices to access
01300 parameters of the procedure doing the calling.
01400
01500 [2] Whenever a SAIL procedure is called, all accumulators except
01600 SP ('16) and P ('17) are available for its use.
01700
01800 [3] Some String operations require that the left half of
01900 pointers to descriptors be negative. Therefore any
02000 operation which obtains a String descriptor address does a
02100 HRRO or HRROI to accomplish this. In this case it is not
02200 necessary, but it won't hurt anything. String reference
02300 parameters always point to the second word of the String in
02400 question.
02500
00100 SAILON NO. 57.2 SAIL 18-1
00200
00300 SECTION 18
00400
00500 APPENDIX -- USEFUL SUMMARIES
00600
00700
00800
00900 ARITHMETIC TYPE-CONVERSION TABLE
01000
01100
01200 18-1.
01300
01400
01500
01600 OPERATION ARG1 ARG2 ARG1' ARG2' RESULT
01700
01800 + - INT INT INT INT INT*
01900 * ↑ % REAL INT REAL REAL REAL
02000 INT REAL REAL REAL REAL
02100 REAL REAL REAL REAL REAL
02200
02300 LAND LOR INT INT INT INT INT
02400 EQV XOR REAL INT REAL INT REAL
02500 INT REAL INT REAL INT
02600 REAL REAL REAL REAL REAL
02700
02800 LSH ROT INT INT INT INT INT
02900 REAL INT REAL INT REAL
03000 INT REAL INT INT INT
03100 REAL REAL REAL INT REAL
03200
03300 / INT INT REAL REAL REAL
03400 REAL INT REAL REAL REAL
03500 INT REAL REAL REAL REAL
03600 REAL REAL REAL REAL REAL
03700
03800 MOD DIV INT INT INT INT INT
03900 REAL INT INT INT INT
04000 INT REAL INT INT INT
04100 REAL REAL INT INT INT
04200
04300 * Unless ARG2 is <0 for the operator ↑
00100 SAILON NO. 57.2 SAIL 18-2
00200
00300
00400
00500 SAIL RESERVED WORDS
00600
00700
00800 18-2.
00900
01000 ABS AND ANY ARRAY ARRAY_PDL ASSOC BBPP BEGIN BOOLEAN CASE COMMENT
01100 CONTINUE COP CVI CVN DATUM DEFINE DELETE DIV DO DONE DPB ELSE END
01200 ENTRY EQV ERASE EXTERNAL FALSE FIRST FOR FOREACH FORTRAN FORWARD FROM
01300 GEQ GLOBAL GO GOTO IBP IDPB IF ILDB IN INF INTEGER INTER INTERNAL
01400 ISTRIPLE ITEM ITEMVAR LABEL LAND LDB LENGTH LEQ LET LIBRARY
01500 LOAD_MODULE LNOT LOP LOR LSH MAKE MAX MESSAGE MIN MOD NEEDNEXT NEQ
01600 NEXT NEW NEW_ITEMS NOT NULL OF OR OWN PHI PNAMES PRELOAD_WITH
01700 PROCEDURE PUT QUICK_CODE REAL RECURSIVE REFERENCE REMOVE REQUIRE
01800 RETURN ROT SAFE SECOND SEGMENT_NAME SEGMENT_FILE SET SETC SETO SHORT
01900 START_CODE STEP STRING STRING_PDL STRING_SPACE SOURCE_FILE SUCH SWAP
02000 SYSTEM_PDL THAT THEN THIRD TO TRUE UNTIL VALUE WHILE XOR
02100
02200
02300 SAIL PRE-DECLARED IDENTIFIERS
02400
02500
02600 18-3.
02700
02800 ARRBLT ARRINFO ARRTRAN ARRYIN ARRYOUT BACKUP BREAKSET CALL CLOSE
02900 CLOSIN CLOSO CLRBUF CODE CVASC CVD CVE CVF CVFIL CVG CVIS CVO CVOS
03000 CVS CVSI CVSIX CVSTR CVXSTR ENTER EQU FILEINFO GETCHAN GETFORMAT
03100 INCHRW INCHRS INCHSL INCHWL INSTR INSTRL INSTRS INPUT INTIN INTSCAN
03200 LINOUT LODED LOOKUP MTAPE OPEN OUT OUTCHR OUTSTR PTCHRS PTCHRW PTIFRE
03300 PTOCNT PTOCHS PTOCHW PTOSTR PTYALL PTYGET PTYIN PTYREL PTYSTR REALIN
03400 REALSCAN RELEASE RENAME SCAN SETBREAK SETFORMAT STRBRK TTYIN TTYINL
03500 TTYINS WORDIN WORDOUT USERCON USERERR USETI USETO
00100 SAILON NO. 57.2 SAIL 18-4
00200
00300
00400
00500 CHARACTER-IDENTIFIER EQUIVALENCES
00600
00700
00800 18-4.
00900
01000
01100 CHARACTER RESERVED WORD
01200
01300 ∧ AND
01400 ≡ EQV
01500 ¬ NOT
01600 ∨ OR
01700 ⊗ XOR
01800 ∞ INF
01900 ε IN
02000 | SUCH THAT
02100 ≠ NEQ
02200 ≤ LEQ
02300 ≥ GEQ
02400 { SETO
02500 } SETC
02600 ∪ UNION
02700 ∩ INTER
02800 ` ASSOC
02900 ↔ SWAP
03000 _ !
03100
00100 SAILON NO. 57.2 SAIL 18-5
00200
00300
00400
00500 PARAMETERS TO THE OPEN FUNCTION
00600
00700
00800 18-5.
00900
01000
01100 CHANNEL System Data Channel, 0-'17
01200
01300 DEVICE string giving device name
01400
01500 MODE data mode, bits 18-21, 23 enable error returns
01600
01700 INBUFS number of input buffers, lh buffer size if ≠0
01800
01900 OUTBUFS number of output buffers
02000
02100 COUNT text input count (reference)
02200
02300 BRCHAR break char variable (reference)
02400
02500 EOF end-of-file and IO error flag (reference)
00100 SAILON NO. 57.2 SAIL 18-6
00200
00300
00400
00500 BREAKSET MODES
00600
00700
00800 18-6.
00900
01000 I (Inclusion) string is set of break chars
01100
01200 X (eXclusion) string of all non-break chars
01300
01400 O (Omit) string of characters to be omitted from result
01500
01600
01700 S (skip) break char appears only in BRCHAR variable
01800
01900 A (Append) break char is last char of result string
02000
02100 R (Retain) break char is first char of next string
02200
02300
02400 P (Pass) line numbers appear in input without warning
02500
02600 N (No numbers) line numbers and the tabs that follow them
02700 are removed.
02800
02900 L (Line no break) line numbers cause input break. BRCHAR
03000 is negative. Next input gets line no characters.
03100
03200 E (Erman) line numbers cause input break. Negated line no
03300 returned in BRCHAR. Line no removed from input.
03400
03500 D (Display) after this appears, each line no is listed on
03600 the display (if TTY is a DPY) as it is dealt with.
00100 SAILON NO. 57.2 SAIL 18-7
00200
00300
00400
00500 MTAPE COMMANDS
00600
00700
00800 18-7.
00900
01000
01100
01200 MODE FUNCTION
01300
01400
01500 "A" Advance past one tape mark (or file)
01600
01700 "B" Backspace past one tape mark
01800
01900 "F" Advance one record
02000
02100 "R" Backspace one record
02200
02300 "W" Rewind tape
02400
02500 "E" Write tape mark
02600
02700 "U" Rewind and unload
02800
00100 SAILON NO. 57.2 SAIL 18-8
00200
00300
00400
00500 COMMAND SWITCHES
00600
00700
00800 18-8.
00900
01000 D double size of define pushdown stack
01100
01200 numL listing control -- num>0 becomes listing starting addr.
01300 num=-1 starts listing after current DDT size. num=-2
01400 starts listing after current RAID size.
01500
01600 numM initial debugging mode set to num
01700
01800 P double size of system pushdown list
01900
02000 Q double size of string pushdown list
02100
02200 R double size of parse pushdown list
02300
02400 numS set size of string space to num
02500
02600 C create CREF (cross-reference) input file.
02700
02800 numF enable various listing formats.
02900
03000
03100 DEBUGGING MODES
03200
03300
03400 18-9.
03500
03600 1 display before executing each code generation routine
03700
03800 2 don't display, but remain enabled for asynchronous and
03900 line breaks
04000
04100 3 display before each production is compared
04200
04300 4 continue from type 1 and 3 modes automatically
04400
04500 5 just display input file as it goes past
04600
04700 6 disable debugging mechanism (started in this mode unless
04800 an M switch appears).
00100 SAILON NO. 57.2 SAIL 18-10
00200
00300
00400
00500 VALID RESPONSES TO ERROR MESSAGES
00600
00700
00800 18-10.
00900
01000 CR (carriage return) try to continue
01100
01200 LF (line feed) continue automatically -- don't stop for
01300 user go-ahead after each message
01400
01500 S restart
01600
01700 X exit -- close all files, return to monitor
01800
01900 L look at stacks -- of interest only to compiler fixers
02000
02100 E edit. Follow by CR to get file the compiler is working
02200 on (or last thing edited, for runtime routines). Follow
02300 with <name> CR to edit <name>.
02400
02500 D go to DDT or RAID
00100 SAILON NO. 57.2 SAIL 18-11
00200
00300
00400
00500 NON-FATAL ERROR, EXCEPTIONAL CONDITION RETURN CODES
00600
00700 18-11.
00800
00900
01000 ROUTINE CODE LOCATION CONDITIONS, CODE VALUES
01100
01200 CALL _SKIP_ set TRUE if the UUO skips, FALSE otherwise
01300
01400 CODE _SKIP_ set TRUE if the constructed instruction
01500 skips, FALSE otherwise
01600
01700 CVFIL _SKIP_ set TRUE if the file input is invalidly
01800 specified (wrong punctuation, order, etc.),
01900 FALSE otherwise.
02000
02100 CVIS FLAG param set TRUE if no PNAME exists for this Item,
02200 FALSE if CVIS succeeds.
02300
02400 CVSI FLAG param set TRUE if no Item exists with this String
02500 as PNAME, FALSE if CVSI succeeds.
02600
02700 ENTER FLAG param set FALSE if the ENTER succeeds. Otherwise,
02800 the left half is made -1. Then if the file
02900 name was invalid, the right half is made
03000 '10. Otherwise it is set to some code from
03100 0 to 7, depending on the type of ENTER
03200 failure. These codes are the same as the
03300 ENTER UUO codes in [Moorer]. If error '10
03400 (invalid spec.) is returned, an error
03500 message (non-fatal) will also be printed,
03600 unless you are enabled for user handling of
03700 this error (see I/O below).
03800
03900 GETCHAN result <0 if no channel is available.
04000
04100 INCHRS result <0 if no characters are waiting.
04200
04300 INCHSL FLAG param ≠0 if no characters are waiting.
04400
04500 INSTRS FLAG param ≠0 if no characters are waiting.
00100 SAILON NO. 57.2 SAIL 18-11
00200
00300
00400 I/O EOF vbl. 0 if no exceptional conditions occurred in
00500 an I/O operation. Otherwise, the left half
00600 has certain bits turned on, indicating the
00700 error: 400000 is a catchall -- improper
00800 mode.
00900 200000 means parity error occurred.
01000 100000 means a data error occurred.
01100 40000 means "Record number out of bounds".
01200 20000 means End of File (input only).
01300 You are always enabled for bit 20000 (EOF).
01400 However, to be allowed to handle any of the
01500 others, you must turn on the corresponding
01600 bit in the right half of the MODE word in
01700 the OPEN for this channel. In addition, the
01800 10000 bit is used to enable user handling of
01900 invalid file specifications to ENTER,
02000 LOOKUP, and RENAME (see above). '7500017 in
02100 the MODE parameter would enable a dump mode
02200 file for user handling of ALL I/O errors on
02300 this channel. If you are not enabled for a
02400 given error, an error message (which may or
02500 may not be fatal) will be printed, and the
02600 error code word set as indicated. In
02700 addition, the number of words actually
02800 transferred is stored in the right half of
02900 this variable for ARRYIN, ARRYOUT.
03000
03100 LOOKUP FLAG param same as ENTER.
03200
03300 OPEN EOF vbl if 0 on entry, prints fatal error message if
03400 OPEN fails. If ≠0 on entry, always returns
03500 to user -- still ≠0 if OPEN failed, 0 if it
03600 succeeded.
03700
03800 RENAME FLAG param same as ENTER.
03900
04000 TTYINS FLAG param same as INSTRS.
00100 SAILON NO. 57.2 SAIL 18-11
00200
00300
00400 substrings _SKIP_ consider ST[X TO Y]. If Y>LENGTH(ST), Y←
00500 LENGTH(ST). If Y<0, Y←0; rh(_SKIP_)←-1 with
00600 both. If X<1, X←1. If X>Y it is set to
00700 Y+1 (guaranteeing a null String result). In
00800 either case, lh(_SKIP_) is set to -1. The
00900 ST[X FOR Y] case is first converted to the
01000 other case, then executed.
01100
01200 You should also refer to the table for Input, 12-40, describing the
01300 various combinations of the BRCHAR and EOF
01400 variables and their meanings.
00100 SAILON NO. 57.2 SAIL 19-1
00200
00300 SECTION 19
00400
00500 BIBLIOGRAPHY
00600
00700
00800
00900 19-1.
01000
01100
01200 REFERENCE DESCRIPTION
01300
01400
01500 Feldman Feldman, J.A. and Rovner, P.D. An Algol-Based
01600 Associative Language, Comm. ACM 12, 8 (Aug.
01700 1969), 439-449.
01800
01900
02000 Moorer Moorer, J.A. Stanford A-I Project Monitor
02100 Manual, Sailons 54 and 55 (Sep. 1969).
02200
02300
02400 Weiher Weiher, W.F. Loader Input Format, Sailon 46
02500 (Oct. 1968).
02600
02700
02800 Savitzky Savitzky, S.R. Son of Stopgap, Sailon 50.1,
02900 (Sep. 1969), a revision of Stopgap, Sailon 50,
03000 by W.F. Weiher.
00100 SAILON NO. 57.2 SAIL 19-1
00200
00300 INDEX
00400
00500 10- 1 <λ_associative_expr>
00600 10- 1 <λ_derived_set>
00700 10- 1 <λ_item_expr_list>
00800 10- 1 <λ_item_expression>
00900 10- 1 <λ_set_expression>
01000 10- 1 <λ_set_factor>
01100 10- 1 <λ_set_primary>
01200 10- 1 <λ_set_term>
01300 7- 1 <λ_triple>
01400 10- 1 <λ_triple>
01500 9-54 Abs
01600 8- 1 <ac_field>
01700 6- 1 <actual_parameter>
01800 6- 1 <actual_parameter_list>
01900 9- 1 <actual_parameter_list>
02000 9- 1 <actual_parameter>
02100 13- 9 Actual Parameter Expansion
02200 6- 4 Actual Parameters
02300 9- 1 <adding_expression>
02400 9- 1 <adding_operator>
02500 9-30 Adding Expressions
02600 8- 1 <address>
02700 8- 1 <addresses>
02800 4- 1 <algebraic_assignment>
02900 9- 1 <algebraic_expression>
03000 9- 1 <algebraic_relational>
03100 3- 1 <algebraic_type>
03200 9- 1 <algebraic_variable>
03300 9 ALGEBRAIC EXPRESSIONS
03400 9-15 Algebraic Expressions
03500 10- 7 ANY Construct
03600 18 APPENDIX -- USEFUL SUMMARIES
03700 11-15 Arithmetic Constants
03800 9-21 Arithmetic Type Conversions
03900 3- 1 <array_declaration>
04000 3- 1 <array_list>
04100 3- 1 <array_segment>
04200 17-37 Array Allocation
04300 3-25 Array Declarations
04400 17-35 ARRAY IMPLEMENTATION
04500 3-31 Arrays, outer block
04600 3-30 Arrays, OWN
04700 3-26 Arrays, SAFE declaration
04800 3-27 Arrays, storage convention
04900 12-112 Arrblt
05000 12-110 Arrinfo
05100 12-114 Arrtran
00100 SAILON NO. 57.2 SAIL 19-1
00200
00300 12-50 Arryin
00400 12-55 Arryout
00500 16-12 Assembly Language Procedures
00600 8 ASSEMBLY LANGUAGE STATEMENTS
00700 4- 1 <assignment>
00800 9- 1 <assignment_expression>
00900 4- 1 <assignment_statement>
01000 9- 4 Assignment Expressions
01100 4- 7 Assignment statement, DATUM
01200 4- 3 Assignment statement, semantics
01300 4- 8 Assignment statement, Swap
01400 4 ASSIGNMENT STATEMENTS
01500 7- 1 <associative_context>
01600 10- 1 <associative_expression>
01700 10- 1 <associative_operator>
01800 7- 1 <associative_statement>
01900 7-18 Associative context, satisfaction
02000 11 BASIC CONSTRUCTS
02100 19 BIBLIOGRAPHY
02200 14- 1 <binary_name>
02300 7- 1 <binding_list>
02400 2- 1 <block>
02500 2- 1 <block_head>
02600 2- 1 <block_name>
02700 2- 9 Block Names
02800 3-20 Block structure, for items
02900 3-14 Boolean, declaration
03000 9- 1 <boolean_expression>
03100 10- 9 Boolean constructs, for LEAP
03200 9-10 Boolean Expression, anomaly
03300 7-16 Boolean expressions, if FOREACH specifications
03400 9-56 Boolean Primaries
03500 3- 1 <bound_pair>
03600 3- 1 <bound_pair_list>
03700 9- 1 <bounded_expression>
03800 9-29 Bounded Expressions
03900 7-11 Bracketed Triples
04000 9-57 Bracketed triples, ISTRIPLE
04100 10- 5 Bracketed triples, selectors
04200 7-14 Breakpoints, MAKE and ERASE
04300 12-22 Breakset
04400 4- 1 <byte_statement>
04500 12-127 Byte pointers, creation
04600 4-10 Byte statements
04700 12-118 Call
04800 17-12 Caninc
04900 9- 1 <case_expression>
05000 5- 1 <case_statement>
05100 5- 1 <case_statement_head>
00100 SAILON NO. 57.2 SAIL 19-1
00200
00300 9- 6 Case Expressions
00400 5-18 Case Statements
00500 12-10 Close, Closin, Closo
00600 12-116 Code
00700 8- 1 <code_begin>
00800 8- 1 <code_block>
00900 8- 1 <code_head>
01000 8- 1 <code_tail>
01100 14- 1 <command_line>
01200 14- 1 COMMAND FORMAT
01300 2-10 Comment
01400 11-24 Comments
01500 14 COMPILER OPERATION
01600 2- 1 <compound_statement>
01700 2- 1 <compound_tail>
01800 9-38 Concatenation Operator
01900 9- 1 <conditional_expression>
02000 5- 1 <conditional_statement>
02100 9- 2 Conditional Expressions
02200 5- 2 Conditional Statements
02300 5- 6 Conditional Statements, ambiguity
02400 11-15 Constants, arithmetic
02500 11-16 Constants, octal
02600 11-17 Constants, real
02700 11-19 Constants, string
02800 7- 8 Construction, definition
02900 10- 1 <construction_item_prim>
03000 5- 1 <continue_statement>
03100 5-30 Continue Statement
03200 4- 6 Conversions, algebraic
03300 9-21 Conversions, algebraic
03400 9-12 Conversions, Boolean to Integer
03500 3-36 Conversions, for preloaded arrays
03600 3-17 Conversions, string
03700 9-27 Conversions, strings
03800 9-11 Conversions, to BOOLEAN
03900 10- 4 COP, of set
04000 17-13 Corbig
04100 17- 6 Corget
04200 17-11 Corinc
04300 17-10 Correl
04400 12-105 Cvasc
04500 12-101 Cvd
04600 12-92 Cve, Cvf, Cvg
04700 12-109 Cvfil
04800 10- 8 CVI
04900 12-84 Cvis
05000 9-52 Cvn
05100 12-103 Cvo
00100 SAILON NO. 57.2 SAIL 19-1
00200
00300 12-82 Cvos
00400 12-80 Cvs
00500 12-86 Cvsi
00600 12-107 Cvsix
00700 12-97 Cvstr
00800 12-99 Cvxstr
00900 7- 3 DATUM, use of
01000 4- 7 Datum Assignments
01100 11- 6 Datums
01200 15- 9 DEBUGGING
01300 14-14 Debugging modes
01400 3- 1 <declaration>
01500 2- 3 Declarations
01600 3 DECLARATIONS
01700 8- 3 Declarations in Code Blocks
01800 3- 1 <define_body>
01900 3- 1 <define_identifier>
02000 3- 1 <define_specification>
02100 3-56 Define Specification
02200 13- 1 Defining Macros
02300 3- 1 <definition>
02400 3- 1 <definition_list>
02500 12-90 Del_Pname
02600 7-10 DELETE
02700 14- 1 <device_name>
02800 9- 1 <disjunctive_expression>
02900 9-18 Disjunctive Expressions
03000 8- 7 Distinctions Between START_CODE and QUICK_CODE
03100 5- 1 <do_statement>
03200 5-17 Do Statement
03300 5- 1 <done_statement>
03400 5-24 Done Statement
03500 4-10 DPB
03600 7- 1 <element>
03700 2- 1 <entry_specification>
03800 2-11 Entry Specifications
03900 12-73 Equ
04000 7-13 ERASE
04100 7-13 ERASE, restriction
04200 14-19 ERROR MESSAGES
04300 5 EXECUTION CONTROL STATEMENTS
04400 12 EXECUTION TIME ROUTINES
04500 9- 1 <expression>
04600 9- 1 <expression_list>
04700 9-14 Expression Evaluation Rules
04800 3- 2 EXTERNAL declaration
04900 3-47 External Procedures
05000 9- 1 <factor>
05100 9-39 Factors
00100 SAILON NO. 57.2 SAIL 19-1
00200
00300 11-18 FALSE, definition
00400 14- 1 <file_ext>
00500 14- 1 <file_name>
00600 3- 1 <file_spec>
00700 14- 1 <file_spec>
00800 10- 5 FIRST, of bracketed triple
00900 5- 1 <for_list>
01000 5- 1 <for_list_element>
01100 5- 1 <for_statement>
01200 5-11 For Statements
01300 7-19 FOREACH specification, evaluation
01400 7-15 FOREACH Statement
01500 7-21 FOREACH statement, efficiency considerations
01600 7-20 FOREACH statement, harsh warning
01700 7-22 FOREACH statement, restrictions and warnings
01800 3- 1 <formal_param_decl>
01900 3- 1 <formal_parameter_list>
02000 3- 1 <formal_type>
02100 3-39 Formal Parameters
02200 3-54 FORTRAN, actual parameters
02300 3-49 FORTRAN, declaration
02400 6-12 Fortran Procedures
02500 16-11 Fortran Procedures
02600 3- 2 FORWARD declaration
02700 3-42 Forward Procedure Declarations
02800 9- 1 <function_designator>
02900 9-47 Function Designators
03000 11-12 Functions, predeclared
03100 12-12 Getchan
03200 12-78 Getformat
03300 5- 1 <go_to_statement>
03400 3-54 Go To, restriction
03500 5- 8 Go To Statements
03600 5- 8 Go To Statements, restrictions
03700 12- 6 I/O ROUTINES
03800 4-10 IBP
03900 3- 1 <id_list>
04000 11- 7 Identifiers
04100 4-10 IDPB
04200 5- 1 <if_statement>
04300 5- 4 If Statement
04400 5- 5 If ... Else Statement
04500 9-58 ILDB
04600 17 IMPLEMENTATION INFORMATION
04700 8- 1 <index_field>
04800 8- 1 <indexed_address>
04900 2- 8 Inner block
05000 12-40 Input
05100 8- 1 <instruction>
00100 SAILON NO. 57.2 SAIL 19-1
00200
00300 3-13 Integers, range
00400 3- 2 INTERNAL declaration
00500 3-48 Internal procedures
00600 10- 2 Intersection, sets
00700 1 INTRODUCTION
00800 9-57 ISTRIPLE
00900 3-54 ITEM, procedure
01000 4- 1 <item_assignment>
01100 10- 1 <item_primary>
01200 3- 2 ITEM ARRAYS, nonexistence
01300 10- 4 Item Constructs
01400 3-18 Item Declarations
01500 3-20 Item Genesis
01600 10- 5 Item Selectors
01700 3-19 Items
01800 10- 6 Items, dynamic NEW
01900 7- 4 ITEMS, storage of instances
02000 10- 1 <itemvar_variable>
02100 3-22 Itemvar Declarations
02200 3-23 Itemvars, binding in FOREACH
02300 7-17 ITEMVARS, binding in FOREACH specifications
02400 7-15 ITEMVARS, binding in FOREACH statements
02500 7-23 ITEMVARS, in FOREACH statement
02600 7- 4 ITEMVARS, use
02700 3- 1 <label_declaration>
02800 5- 1 <label_identifier>
02900 3- 4 Label use
03000 3-54 Labels, as actual parameters
03100 9-58 LDB and ILDB
03200 7- 2 LEAP, introduction
03300 7- 7 LEAP, restrictions
03400 9- 1 <leap_relational>
03500 10- 1 <leap_relational>
03600 7- 1 <leap_statement>
03700 3- 1 <leap_type>
03800 10- 9 LEAP Booleans
03900 7 LEAP STATEMENTS
04000 9-50 Length
04100 12-116 LIBERATION-FROM-SAIL ROUTINES
04200 12- 1 Library, runtime
04300 12-46 Linout
04400 14- 1 <listing_name>
04500 8- 1 <literal>
04600 9-53 Lnot
04700 15- 1 LOADING AND STARTING SAIL PROGRAMS
04800 9-30 Logical Expressions
04900 12-17 Lookup, Enter
05000 7- 1 <loop_statement>
05100 9-51 Lop
00100 SAILON NO. 57.2 SAIL 19-1
00200
00300 10- 4 LOP, of set
00400 17-28 Lop Details
00500 3- 1 <lower_bound>
00600 13- 6 Macro Parameters
00700 16- 2 Main Program
00800 7-11 MAKE
00900 7-13 MAKE, restriction
01000 8- 4 Meaning of Instruction Operands
01100 12-57 Mtape
01200 9- 1 <mult_operator>
01300 9- 1 <negated_expression>
01400 10- 6 NEW_ITEM Declaration
01500 12-88 New_Pname
01600 10- 6 NEW Items
01700 5- 1 <next_statement>
01800 5-26 Next Statement
01900 18-11 NON-FATAL ERROR, EXCEPTIONAL CONDITION RETURN CODES
02000 11-21 NULL, definition
02100 3-13 Numeric Declarations
02200 8- 1 <opcode>
02300 12- 6 Open
02400 12-45 Out
02500 2- 8 Outer block
02600 10- 3 PHI, the empty set
02700 12-126 Point
02800 9-13 Precedence of Algebraic Operators
02900 3- 1 <preload_element>
03000 3- 1 <preload_list>
03100 3- 1 <preload_specification>
03200 3-33 Preload Specifications
03300 9-40 Primaries
03400 9- 1 <primary>
03500 3- 1 <procedure_body>
03600 3- 1 <procedure_declaration>
03700 3- 1 <procedure_head>
03800 6- 1 <procedure_statement>
03900 3- 5 Procedure body, emptiness
04000 17-51 Procedure Calling Sequences
04100 6- 4 Procedure Calls, actual parameters
04200 6- 2 Procedure Calls, semantics
04300 3-38 Procedure Declarations
04400 17-48 PROCEDURE IMPLEMENTATION
04500 6 PROCEDURE STATEMENTS
04600 6-10 Procedures, as actual parameters
04700 3-53 Procedures, defaults in declarations
04800 3-51 Procedures, parametric
04900 3-54 Procedures, restrictions
05000 2- 1 <program>
05100 2- 9 Program name, for DDT
00100 SAILON NO. 57.2 SAIL 19-1
00200
00300 15 PROGRAM OPERATION
00400 16 PROGRAM STRUCTURE
00500 2 PROGRAMS, BLOCKS, STATEMENTS
00600 14- 1 <proj_prog>
00700 12-70 Pseudo-teletype functions (Stanford only)
00800 7- 9 PUT, use
00900 12-61 Realin, Intin
01000 3-13 Reals, range
01100 12-66 Realscan, Intscan
01200 3- 2 RECURSIVE declaration
01300 3-44 Recursive Procedures
01400 3-39 REFERENCE
01500 3-53 REFERENCE
01600 6- 6 REFERENCE, actual parameters
01700 9- 1 <relational_expression>
01800 9- 1 <relational_operator>
01900 9-19 Relational Expressions
02000 12-14 Release
02100 7- 9 REMOVE, use
02200 12-21 Rename
02300 10- 6 REQUIRE, new_items
02400 3- 1 <require_element>
02500 3- 1 <require_list>
02600 3-57 REQUIRE declaration
02700 3- 1 <requirement>
02800 3-57 Requirements
02900 11-10 Reserved words, list of
03000 11-11 Reserved words, "Global Model"
03100 7- 8 Retrieval, definition
03200 10- 1 <retrieval_item_prim>
03300 9-47 RETURN, value of function
03400 5- 1 <return_statement>
03500 5-20 Return Statement
03600 14-12 Rpg Mode
03700 11-12 Runtime routines, list of
03800 11-13 Runtime routines, Stanford Only
03900 3- 2 SAFE declaration
04000 7-18 Satisfiers, of associative context
04100 7-19 Satisfiers, of associative context
04200 12-43 Scan
04300 3- 8 Scope of declarations
04400 10- 5 SECOND, of bracketed triple
04500 10- 1 <selector>
04600 16- 7 Separately Compiled Procedures
04700 4- 1 <set_assignment>
04800 10- 1 <set_expression>
04900 7- 1 <set_statement>
05000 10- 1 <set_variable>
05100 10 SET AND ASSOCIATIVE EXPRESSIONS
00100 SAILON NO. 57.2 SAIL 19-1
00200
00300 3-24 Set Declarations
00400 10- 2 Set Expressions
00500 10- 3 Set Primaries
00600 12-35 Setbreak
00700 12-75 Setformat
00800 10- 3 Sets, derived from associations
00900 7-15 SETS, in FOREACH specifications
01000 7- 5 SETS, use
01100 9-24 Short Integer↔Real Conversions
01200 8- 1 <simple_address>
01300 9- 1 <simple_expression>
01400 9- 9 Simple Expressions
01500 3- 1 <simpler_formal_type>
01600 14- 1 <slashed_switch_list>
01700 14- 1 <source_list>
01800 3- 1 <space_spec>
01900 9-45 Special Length Operator (∞)
02000 15- 2 Starting the Program -- Normal Operation
02100 15- 3 Starting the Program in "RPG" Mode
02200 15- 4 Starting the Program with Allocation Modifications
02300 2- 1 <statement>
02400 2- 6 Statements
02500 12-37 Stdbrk
02600 14-22 STORAGE ALLOCATION
02700 17- 5 Storage Allocation Routines
02800 17- 1 STORAGE LAYOUT
02900 9-27 String-Arithmetic Conversions
03000 9- 1 <string_expression>
03100 17-33 String-Oriented Machine Language Routines
03200 9- 1 <string_variable>
03300 2-10 String constant, as comment.
03400 11-19 String Constants
03500 3-15 String Declarations
03600 17-15 String Descriptors
03700 17-32 String Garbage Collection
03800 12-72 STRING MANIPULATION ROUTINES
03900 17-20 String Operations
04000 17-29 String Space
04100 17-15 STRINGS
04200 11- 1 <subscript_list>
04300 9- 1 <substring_spec>
04400 9-42 Substrings
04500 10- 2 Subtraction, sets
04600 4- 1 <swap_statement>
04700 4- 8 Swap Assignment
04800 4- 2 Swap operator, restriction
04900 14- 1 <switch_spec>
05000 14- 1 <switches>
05100 14-13 Switches
00100 SAILON NO. 57.2 SAIL 19-1
00200
00300 15-10 Symbols
00400 3- 1 <synonym>
00500 3- 1 <synonym_declaration>
00600 3- 1 <synonym_list>
00700 3-55 Synonyms
00800 12-68 Teletype I/O Functions
00900 9- 1 <term>
01000 9-33 Terms
01100 16- 1 THE SAIL CORE IMAGE (REQUIRED)
01200 10- 5 THIRD, of bracketed triple
01300 7-12 Triples, bracketed
01400 7-17 Triples, in FOREACH specifications
01500 11-18 TRUE, definition
01600 3- 1 <type>
01700 3- 1 <type_declaration>
01800 3- 1 <type_qualifier>
01900 12-75 TYPE CONVERSION ROUTINES
02000 3-11 Type Declarations
02100 9-55 Unary Minus
02200 10- 2 Union, sets
02300 14- 1 <unslashed_switch_list>
02400 3- 1 <upper_bound>
02500 13 USE OF DEFINE
02600 17- 1 User Table
02700 12-120 Usercon
02800 12-124 Usererr
02900 12-59 Useti, Useto
03000 13- 5 Using Macros
03100 14- 1 <valid_switch_name>
03200 3-39 VALUE
03300 3-53 VALUE
03400 6- 5 VALUE, actual parameters
03500 11- 1 <variable>
03600 3-11 Variables
03700 11- 2 Variables
03800 8- 8 Warning Concerning Default Radix
03900 5- 1 <while_statement>
04000 5-16 While Statement
04100 12-48 Wordin
04200 12-53 Wordout
04300 7-15 <binding_list>
04400